[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

OpenVMS User's Manual


Previous Contents Index

15.2.2 Changing Default File Protection

You may want to change the default file protection within a command procedure. The following command procedure changes the default protection associated with files created while the procedure is executing. The procedure restores the original default file protection before terminating.


$ SAVE_PROT = F$ENVIRONMENT("PROTECTION")
$ SET PROTECTION = (SYSTEM:RWED, OWNER:RWED, GROUP, WORLD)/DEFAULT
   .
   .
   .
$ SET PROTECTION=('SAVE_PROT')/DEFAULT
$ EXIT

Note that the F$ENVIRONMENT function returns the default protection code using the syntax required by the SET PROTECTION command. This lets you use the symbol SAVE_PROT with the SET PROTECTION command to restore the original default file protection.

15.3 Obtaining Information About the System

You can use the following lexical functions to obtain information about the system:

F$CONTEXT Specifies selection criteria to use with the F$PID function. The F$CONTEXT function enables the F$PID function to obtain information about processes from any node in an OpenVMS Cluster system.
F$CSID Returns an OpenVMS Cluster identification number and updates the context symbol to point to the current position in the system's OpenVMS Cluster node list.
F$GETQUI Returns information about queues, batch and print jobs currently in those queues, form definitions, and characteristic definitions kept in the system job queue file.
F$GETSYI Returns information about your local system or about a node in your OpenVMS Cluster system (if your system is part of an OpenVMS Cluster).
F$IDENTIFIER Converts identifiers from named to numeric format or from numeric to named format.
F$MESSAGE Returns the message text associated with a status code.
F$PID Returns the process identification (PID) number for processes that you are allowed to examine.
F$TIME Returns the current date and time.

15.3.1 Determining Your OpenVMS Cluster Node Name

If your system is part of an OpenVMS Cluster environment where you can log in to many different nodes, you can set the DCL prompt to indicate which node you are currently using. To do this, include the F$GETSYI function in your login command procedure to determine the node name. Then use the SET PROMPT command to set a unique prompt for the node.

If you want to use only a portion of the node name in your prompt string, use the F$EXTRACT function to extract the appropriate characters. See Section 15.6.2 for more information on extracting characters.

In the following example, the symbol NODE is defined as FF$GETSYI("NODENAME") and then the node name is used as the prompt:


$ NODE = F$GETSYI("NODENAME")
$ SET PROMPT = "''NODE'$ "
   .
   .
   .

15.3.2 Obtaining Queue Information

You can use the F$GETQUI function to get many types of information about batch and print queues. You must have read access to the job, SYSPRV privilege, or OPER privilege to obtain information about jobs and files in queues.

The following example shows how to determine if the batch queue VAX1_BATCH is in a stopped state. The value returned is either true or false. If the queue is not stopped, the command procedure submits a job to the queue.


$ QSTOPPED = F$GETQUI("DISPLAY_QUEUE", "QUEUE_STOPPED", "VAX1_BATCH")
$ IF QSTOPPED THEN GOTO NOBATCH
$ SUBMIT/QUEUE=VAX1_BATCH TEST.COM
$ NOBATCH:
   .
   .
   .

15.3.3 Obtaining Process Information

You can use the F$PID function to get the process identification (PID) number for all processes that you are allowed to examine. You can obtain PID numbers:

  • For all processes on the system if you have WORLD privilege
  • For all processes in your group if you have GROUP privilege
  • Only for your process if you have neither GROUP nor WORLD privilege

After you obtain a PID number, you can use the F$GETJPI function to obtain specific information about the process.

The following example shows how to obtain and display the PID numbers for the processes you are allowed to examine:


$ ! Display the time when this procedure
$ ! begins executing
$ WRITE SYS$OUTPUT F$TIME()
$ !
$ CONTEXT = ""
$ START:
$ ! Obtain and display PID numbers until
$ ! F$PID returns a null string
$ !
$ PID = F$PID(CONTEXT)
$ IF PID .EQS. "" THEN EXIT
$ WRITE SYS$OUTPUT "Pid --- ''PID'"
$ GOTO START

The system uses the symbol CONTEXT to hold a pointer into the system list of PID numbers. Each time through the loop, the system changes the pointer to locate the next PID number in the list. The procedure exits after all PID numbers have been displayed.

In the following example, the procedure displays the PID number and the UIC for each process:


$ CONTEXT = ""
$ START:
$ ! Obtain and display PID numbers and UICs
$ !
$ PID = F$PID(CONTEXT)
$ IF PID .EQS. "" THEN EXIT
$ UIC = F$GETJPI(PID,"UIC")
$ WRITE SYS$OUTPUT "Pid --- ''PID'   Uic--- ''UIC' "
$ GOTO START

Note that you can shorten this command procedure by including the F$GETJPI function within the WRITE command, as follows:


$ CONTEXT = ""
$ START:
$ PID = F$PID(CONTEXT)
$ IF PID .EQS. "" THEN EXIT
$ WRITE SYS$OUTPUT "Pid --- ''PID'   Uic --- ''F$GETJPI(PID,"UIC")'"
$ GOTO START

15.3.4 F$CONTEXT Lexical Function

To obtain information about processes from any node in an OpenVMS Cluster system, use the F$CONTEXT function.

In the following example, F$CONTEXT is called three times to set up selection criteria:


$!Establish an error and Ctrl/Y handler
$!
$ ON ERROR THEN GOTO error
$ ON CONTROL_Y THEN GOTO error
$!
$ ctx = ""
$ temp = F$CONTEXT ("PROCESS", ctx, "NODENAME", "*","EQL") (1)
$ temp = F$CONTEXT ("PROCESS", ctx, "USERNAME", "M*,SYSTEM","EQL") (2)
$ temp = F$CONTEXT ("PROCESS", ctx, "CURPRIV", "SYSPRV,OPER", "ALL") (3)
$!
$!Loop over all processes that meet the selection criteria.
$!Print the PID number and the name of the image for each process.
$!
$loop: (4)
$ pid = F$PID(ctx)
$ IF pid .EQS. ""
$ THEN
$     GOTO endloop
$ ELSE
$     image = F$GETJPI(pid,"IMAGNAME") (5)
$     SHOW SYMBOL pid
$     WRITE SYS$OUTPUT image (6)
$     GOTO loop
$ ENDIF
$!The loop over the processes has ended.
$!
$endloop:
$!
$ EXIT
$!
$!Error handler. Clean up the context's memory with
$!the CANCEL selection item keyword.
$!
$error:
$ IF F$TYPE(ctx) .eqs. "PROCESS_CONTEXT" THEN - (7)
-$ temp = F$CONTEXT ("PROCESS", ctx, "CANCEL") (8)
$!
$ EXIT

As you examine the example, note the following:

  1. The first call requests that the search take place on all nodes in the OpenVMS Cluster system.
  2. The second call requests that only the processes whose user name either starts with an M or is SYSTEM be processed.
  3. The third call restricts the selection to those processes whose current privileges include both SYSPRV (system privilege) and OPER (operator) and can have other privileges set.
  4. The command lines between the labels "loop" and "endloop" continually call F$PID to obtain the processes that meet the criteria set up in the F$CONTEXT calls.
  5. After retrieving each PID number, F$GETJPI is called to return the name of the image running in the process.
  6. Finally, the procedure displays the name of the image.
  7. In case of error or a Ctrl/Y operation, control is passed to error and the context is closed if necessary.
  8. Note the check for the symbol type PROCESS_CONTEXT. If the symbol has this type, selection criteria must be canceled by a call to F$CONTEXT. If the symbol is not of the type PROCESS_CONTEXT, either selection criteria have not been set up yet in F$CONTEXT or the symbol was used with F$PID until an error occurred or until the end of the process list was reached.

15.4 Obtaining Information About Files and Devices

You can use the following lexical functions to obtain information about files and devices:

F$DEVICE Returns the device names of all devices on a system that meet the specified selection criteria
F$FILE_ATTRIBUTES Returns information about file attributes
F$GETDVI Returns information about a specified device
F$PARSE Parses a file specification and returns the requested field or fields
F$SEARCH Searches a directory for a file

15.4.1 Searching for Devices

To get information on a particular device by using the system service $GETDVI, you must provide the device name to the service. If you do not know the device name, you can find it by using the lexical function F$DEVICE.

The F$DEVICE function allows wildcard searches based on the device name, the device class, or the device type. To do a search based on device type, you must also specify a device class.

You can use the F$DEVICE function in a loop in a command procedure to return device names that match the specified selection criteria. Each time the F$DEVICE function is executed, it returns the next device on the system that matches the selection criteria. Note that devices are returned in no particular order. After the last device name is returned, the next F$DEVICE function call returns a null string.

This command procedure displays the device names of all the RA60s on a unit numbered 0:


$ START:
$     DEVICE_NAME = F$DEVICE("*0:","DISK","RA60")
$     IF DEVICE_NAME .EQS. "" THEN EXIT
$     SHOW SYMBOL DEVICE_NAME
$     GOTO START

15.4.2 Searching for a File in a Directory

Before processing a file, a command procedure should use the F$SEARCH function to test whether the file exists. For example, the following command procedure uses F$PARSE to apply a device and directory string to the file STATS.DAT. Then the procedure uses the F$SEARCH function to determine whether STATS.DAT is present in DISK3:[JONES.WORK]. If it is, the command procedure processes the file. Otherwise, the command procedure prompts for another input file.


$ FILE = F$PARSE("STATS.DAT","DISK3:[JONES.WORK]",,,"SYNTAX_ONLY")
$ IF F$SEARCH(FILE) .EQS. "" THEN GOTO GET_FILE
$ PROCESS_FILE:
   .
   .
   .
$ GET_FILE:
$   INQUIRE FILE "File name"
$   GOTO PROCESS_FILE

After determining that a file exists, the procedure can use the F$PARSE or the F$FILE_ATTRIBUTES function to get additional information about the file. For example:


$ IF F$SEARCH("STATS.DAT") .EQS. "" THEN GOTO GET_FILE
$ PROCESS_FILE:
$     NAME = F$PARSE("STATS.DAT",, "NAME")
   .
   .
   .
$ GET_FILE:
$   INQUIRE FILE "File name"
$   GOTO PROCESS_FILE

15.4.3 Deleting Old Versions of Files

If a command procedure creates files that you do not need after the procedure terminates, delete or purge these files before you exit from the procedure. Use the PURGE command to delete all versions except the most recent one. Use the DELETE command with a version number to delete a specific version of the file or with a wildcard character in the version field to delete all versions of the file.

To avoid error messages when using the DELETE command within a command procedure, use the F$SEARCH function to verify that a file exists before you try to delete it. For example, you can write a command procedure that creates a file named TEMP.DAT only if certain modules are executed. The following line issues the DELETE command only if TEMP.DAT exists:


$ IF F$SEARCH("TEMP.DAT") .NES. "" THEN DELETE TEMP.DAT;*

15.5 Translating Logical Names

You can use the following lexical functions to translate logical names:

F$LOGICAL Returns the equivalence string for a logical name.
F$TRNLNM Returns either the equivalence string or the requested attributes for a logical name.

Note

The F$TRNLNM function supersedes the F$LOGICAL function that was used in earlier versions of the OpenVMS operating system. You should use F$TRNLNM (instead of F$LOGICAL) to ensure that your command procedure processes logical names using the current system techniques.

In some situations, you may want to use logical names rather than symbols as variables in command procedures. Programs can access logical names more easily than they can access DCL symbols. Therefore, to pass information to a program that you run from a command procedure, obtain the information using a symbol. Then use the DEFINE or ASSIGN command to equate the value of the symbol to a logical name.

You can also use the F$TRNLNM function to determine the value of a logical name and then assign the value to a symbol.

The following example tests whether the logical name NAMES has been defined. If it has, the procedure runs PAYROLL.EXE. Otherwise, the procedure obtains a value for the symbol FILE and uses this value to create the logical name NAMES. PAYROLL.EXE uses the logical name NAMES to refer to the file of employee names.


$ ! Make sure that NAMES is defined
$ IF F$TRNLNM("NAMES") .NES. "" THEN GOTO ALL_SET
$ INQUIRE FILE "File with employee names"
$ DEFINE NAMES 'FILE'
$ !
$ ! Run PAYROLL, using the file indicated by NAMES
$ ALL_SET:
$ RUN PAYROLL
   .
   .
   .

This command procedure defines a logical name that is used in the program PAYROLL:


$ DEFINE NAMES DISK4:[JONES]EMPLOYEE_NAMES.DAT
$ RUN PAYROLL
   .
   .
   .
$ WRITE SYS$OUTPUT "Finished processing ",F$TRNLNM("NAMES")

At the end of the procedure, the WRITE command displays a message indicating that the file was processed.

15.6 Manipulating Strings

You can use the following lexical functions to manipulate character strings:

F$CVTIME Returns information about a time string
F$EDIT Edits a character string
F$ELEMENT Extracts an element from a string in which the elements are separated by delimiters
F$EXTRACT Extracts a section of a character string
F$FAO Formats an output string
F$LENGTH Determines the length of a string
F$LOCATE Locates a character or a substring within a string and returns the offset

15.6.1 Determining Presence of Strings or Characters

One common reason for examining strings is to determine whether a character (or substring) is present within a character string. To do this, use the F$LENGTH and the F$LOCATE functions. If the value returned by the F$LOCATE function equals the value returned by the F$LENGTH function, then the character you are looking for is not present.

The following procedure requires a file name that includes the version number. To determine whether a version number is present, the procedure tests whether a semicolon (;), which precedes a version number in a file name, is included in the file name that the user enters.


$ INQUIRE FILE "Enter file (include version number)"
$ IF F$LOCATE(";", FILE) .EQ. F$LENGTH(FILE) THEN -
     GOTO NO_VERSION
   .
   .
   .

The F$LOCATE function returns the offset for the semicolon. Offsets start with 0; thus, if the semicolon were the first character in the string, the F$LOCATE function would return the integer 0. If the semicolon is not present within the string, the F$LOCATE function returns an offset that is one more than the offset of the last character in the string. This value is the same as the length returned by F$LENGTH, which measures the length of the string starting with the number 1.

15.6.2 Extracting Parts of Strings

To extract a portion of a string, use either the F$EXTRACT function or the F$ELEMENT function. Use the F$EXTRACT function to extract a substring that starts at a defined offset. Use the F$ELEMENT function to extract part of a string between two delimiters. To use either of these functions, you must know the general format of the string you are parsing. Note that you do not need to use F$EXTRACT or F$ELEMENT to parse file specifications or time strings. Instead, use F$PARSE or F$CVTIME to extract the desired portions of file specifications or time strings.

You can also determine the length of the group name at the same time you extract it.

If a string contains a delimiter that separates different parts of the string, use the F$ELEMENT function to extract the part that you want. You can use F$ELEMENT to obtain different types of access by extracting the portions of the string between the commas. To determine system access, obtain the first element; to determine owner access, obtain the second element; and so on. Note that when you use the F$ELEMENT function, element numbers start with zero. For this reason, use the integer 3 to specify the fourth element.

The following command procedure uses the F$EXTRACT function to extract the group portion of the UIC. This allows the procedure to execute a different set of commands depending on the user's UIC group.


$ UIC = F$USER()
$ GROUP_LEN = F$LOCATE(",",UIC) - 1
$ GROUP = F$EXTRACT(1,GROUP_LEN, UIC)
$ GOTO 'GROUP'_SECTION
   .
   .
   .
$ WRITERS_SECTION:
   .
   .
   .
$ MANAGERS_SECTION:
   .
   .
   .

First, the procedure determines the UIC with the F$USER function. Next, the procedure determines the length of the group name by using F$LOCATE to locate the offset of the comma. The comma separates the group from the user portion of a UIC. Everything between the left bracket and the comma is part of the group name. For example, the group name from the UIC [WRITERS,SMITH] is WRITERS.

After determining the length, the procedure extracts the name of the group with the F$EXTRACT function. The name starts with offset 1 and ends with the character before the comma. Finally, the procedure directs execution to the appropriate label.

The following example shows how to determine the length of a group name at the same time it is being extracted:


$ UIC = F$USER()
$ GROUP = F$EXTRACT(1, F$LOCATE(",",UIC) - 1, UIC)
$ GOTO 'GROUP'_SECTION

The following example shows how each type of access in a protection code is separated by a comma:


$ PROT = F$ENVIRONMENT("PROTECTION")
$ SHOW SYMBOL PROT
PROT = "SYSTEM=RWED, OWNER=RWED, GROUP=RE, WORLD"

The commands in this example extract the world access portion (the fourth element) from the default protection code:


$ PROT = F$ENVIRONMENT("PROTECTION")
$ WORLD_PROT = F$ELEMENT(3,",",PROT)
   .
   .
   .

The F$ELEMENT function returns everything between the third comma and the end of the string. Thus, if your default protection allowed read access for world users, the string "WORLD=R" would be returned.

After you obtain the world access string, you may need to examine it further. For example:


$ PROT = F$ENVIRONMENT("PROTECTION")
$ WORLD_PROT = F$ELEMENT(3,",",PROT)
$ IF F$LOCATE("=", WORLD_PROT) .EQ. F$LENGTH(WORLD_PROT) -
  THEN GOTO NO_WORLD_ACCESS
   .
   .
   .


Previous Next Contents Index