HP OpenVMS Systems Documentation

Content starts here

Guide to OpenVMS File Applications

Previous Contents Index

5.5 Image Activation Using Logical Names

When an OpenVMS system activates an image, it uses RMS to open the image file. If the program specifies the image file with a logical name, RMS uses the equivalence name to look up the image in the known file list, unless the file specification includes a version number delimiter (a semicolon [;] or a period [.]). Known files are files that are installed using the Install utility, and the known file list provides a listing of these files by name and by number (file ID).

If RMS finds the file in the known file list, it uses the file number to access the file directly on disk and bring it into memory for execution. If the specified image file is not in the known file list, RMS goes through the time-consuming process of looking through the disk directories to find the file.

If you create a new version of an image but do not install it as a known image and do not remove the old version of the image from the known file list, the new image will not run.

Similarly, when you use a search list to specify the image, the known file lookup takes precedence. Until a lookup is successful or until the search list is exhausted, RMS executes a known file lookup for each element on the search list that does not include a file version delimiter. If it exhausts the search list, RMS uses the search list again, this time trying to locate and open the image file on disk.

If an older version of the image is included in the search list and if RMS finds the older version first, it will execute the older version and never look for the new version. Be sure to consider this when using search lists.

5.6 Sample Use of Logical Names

Regardless of the programming language, you can use a logical name to provide components of a file specification. The following program example shows how to access a remote file. You access a remote file in the same way that you access a local file, except that the remote file specification includes a node name.

Example 5-1 is a simple Fortran program that transfers a remote file on node TRNTO to the line printer on node BOSTON, using the logical names SRC and DST. You must define the logical name for the process before you run the program, using the following sequence of commands:


In Example 5-1, standard I/O calls transfer the file's records from one device to another. Note the use of the OpenVMS file specification format with a remote node name. (If the remote node is running a system other than OpenVMS, the format of the file specification may differ.)

After opening the files and copying all the records, the program closes the channels, thereby terminating network operations. These operations are similar for applications in the other high-level languages.

Example 5-1 Using Logical Names for Remote File Access

C       This program creates a sequential file with variable-length
C       records from a sequential input file. The input and output
C       files are identified by the logical names SRC and DST,
C       respectively.
100     FORMAT (Q,A)
200     FORMAT (A)
C       Open the input and output files.
     1       FORM='FORMATTED')
C       Transfer records until end-of-file or other error condition.
10      READ (1,100,END=20,ERR=20) NCHAR,BUFFER(:NCHAR)
        WRITE (2,200) BUFFER(:NCHAR)
        GOTO 10
C       Close the input and output files.
20      CLOSE (UNIT=2)
        CLOSE (UNIT=1)

You can substitute the system logical name defined on a remote system as one or more of the components in the remote file specification, as follows:

  • Device alone
  • Both device and directory
  • Complete file specification if it includes node

A logical name that includes the device, directory, and filename components but does not include the node, as illustrated in the following example, is not supported in a remote file specification:

$DEFINE/SYSTEM myfile work2:[user1]a.a
$DIRECTORY alpha1"user1 password"::myfile
%DIRECT-W-NOFILES, no files found
$DIRECTORY alpha1"user1 password"::myfile:
%DIRECT-E-OPENIN, error opening ALPHA1"USER1 password"::MYFILE:*.*;* as input
-RMS-F-FNM, error in file name

Note that a foreign file specification would work:

$DIRECTORY alpha1"user1 password"::"myfile"
Directory 0"user1 password"::

5.7 Types of Logical Names

When a logical name is defined, you can assign it various translation attributes including the concealed attribute and the terminal attribute. By default, a logical name is neither concealed nor terminal.

To specify a logical name as either concealed or terminal, use the /TRANSLATION_ATTRIBUTES qualifier for the DCL commands DEFINE or ASSIGN.

The terminal attribute indicates that the related logical name is the final name in the translation process. That is, no further translation is to be performed.

The concealed attribute ensures that RMS uses the device logical name when communicating with the application program. If the device logical name does not have the concealed attribute, any file specification information returned to the application program includes the device's physical name rather than its logical name. To illustrate, enter the following command sequence:


The system responds with the following display, which identifies the device by its physical name (DUA5):


FILE.TXT;1        FILE.TXT;2

Total of 2 files.

Now enter the following command sequence:


The system responds with the following display, which identifies the device by its logical name (USERDISK).


FILE.TXT;1        FILE.TXT;2

Total of 2 files.

A search list is a logical name that contains more than one file specification. Typically a search list is used to search multiple file locations looking for a file. RMS attempts to locate the file by using the first file specification in the search list, then the next, and so forth until the file is found or the search list is exhausted. Like other logical names, a search list is usually defined using the ASSIGN or DEFINE commands; however, in a search list logical name, the multiple file specifications (equivalence names) must be separated by commas.

Any of the equivalence names in the search list may be specified individually as being terminal or being concealed. Section 6.2 describes the use of search lists and wildcard characters for multiple file processing and parsing. For general information about using logical names, refer to the OpenVMS User's Manual.

5.8 Introduction to File Parsing

RMS allows an application program to specify defaults for the device and directory components of a file specification as well as other components of a file specification. The method RMS uses to apply defaults and translate any logical names present is called file parsing. In effect, RMS merges the various default strings (after translating any logical names) to generate the file specification used to locate the file.

One of the functions of file parsing is to determine when a logical name is present and whether the file specification describes a file on the local node. If a node name is not present in the file specification (the file is located on the local system), RMS translates any logical names, applies defaults to any missing components, and then attempts to locate the file.

If a node name is present, RMS does not process the file specification on the local node. Instead, it merges any program-specified defaults without translation and passes the defaulted, untranslated file specification to the file access listener (FAL) at the remote node; the operating system on the remote node interprets it.

With advanced file parsing, a single file specification can be used to locate a single file or multiple files. To locate a single file, multiple file locations or file names can be searched to ensure that the file is found. The multiple file locations or file names can be located in the same or in different directories, on different devices, on different nodes, or a combination thereof. Using wildcard characters and search lists, you can locate multiple files with a single file specification.

When a wildcard character or a search list is included in a file specification, the application program may need to preprocess the file specification before attempting to locate the file. An RMS file service that operates on an unopened file (such as the Create service and the Open service) performs the following file-parsing tasks:

  • Examines a file specification for validity
  • Translates any logical names present
  • Applies defaults
  • Attempts to locate the file

If a name block is present, the service may also do the following file-parsing tasks:

  • Returns the actual complete file specification used to access the file and its associated file identifier
  • Returns the length of each component of a file specification as well as other information about the file specification

Some file services, including the Open and Create services, cannot process a file specification that contains wildcard characters. If a file specification contains wildcard characters, you must use the Search service to resolve the wildcard characters before you invoke the Open service or the Create service.

The Parse service determines whether wildcard characters or search lists are present, and it initializes control block fields that are necessary to search for multiple files using the Search service. To use the Search service, a name block (NAM or NAML) must be present when the Parse service is invoked.

Alternatively, you can use the SYS$FILESCAN system service (scan string for file specification) to scan a file specification for validity and optionally return the lengths of the individual file specification components without translating logical names or applying defaults. Two Run-Time Library routines, LIB$FIND_FILE and LIB$FILE_SCAN, perform functions that are similar to the SYS$SEARCH system service.

For more information about how RMS parses a file specification, see Section 6.1. For additional information about using directory specifications, including directory syntax conventions, see Section 6.3.

5.9 Using One File Specification to Locate Many Files

Five services can translate and apply defaults to a file specification to produce a fully qualified file specification: the Create, Open, Erase, Parse, and Rename services. Other file services must be preceded by one of these services to parse the file specification and, in some cases, to open the file.

If a file specification contains one or more wildcard characters, it must be preprocessed using the Parse and Search services before the file can be located. The Parse service sets bit values in the name block file name status bits field (NAM$L_FNB or NAML$L_FNB). This field can be tested to determine whether a wildcard character or a search list logical name is present. The Search service locates a file and specifies its name (without wildcard characters). If wildcard characters are present, you must first invoke the Search service before processing (opening or creating) the file; if wildcard characters are not present, the file can be processed without invoking the Search service.

To process a single file, you need to invoke the Search service only once; to process many files, invoke the Search service as many times as needed to return the next full file specification. When no more files match the file specification, the Search service returns a no-more-files-found message (RMS$_NMF).

In summary, the Parse and Search services work together to provide a fully qualified file specification that the Search service uses to locate the file.

Your program can process a single file without using the Search service if neither the file specification nor the search list contain wildcard characters. If any of the file specifications in a search list contain wildcard characters, the Search service must be invoked before processing the file to prevent an invalid wildcard completion status error. If a wildcard character is present in the second or subsequent file specifications in a search list, RMS does not set the wildcard bit in the file name status bits field.

If the Parse and Search services precede an Open service, an open-by-name-block operation should be performed by specifying the address of the name block in the name block address (FAB$L_NAM or FAB$L_NAML) field and setting the file-processing options (FAB$L_FOP) open-by-name-block (FAB$V_NAM) bit option.

Wildcard characters cannot be present in the file specification when the Create service is invoked. Sometimes the Parse service and the Search service precede a Create service.

When the create-if option bit (FAB$V_CIF) or the supersede option bit (FAB$V_SUP) is set in the file-processing options (FAB$L_FOP) field, the program may invoke the Parse service to check for wildcard characters or search lists in the file specification. If a search list or wildcard characters are found, the program must invoke the Search service before invoking the Create service.

The create-if option tries to open any file found in the search list. If the file is not found in the search list, RMS creates it using the first file specification in the search list. If these options are specified and a wildcard character is present when the Create service is invoked, the file specification is invalid; if a search list is present, the file is created using the first file specification from the search list.

You can either call these services directly from a VAX MACRO procedure, as part of a USEROPEN or USER_ACTION routine in a high-level language, or you may execute the calls from high-level language subroutines or functions that call RMS. The Parse and Search services require that a name block be present. Unless your language supports a means of setting values in a name block (and other control blocks) and invoking RMS, you should use a VAX MACRO procedure. FDL does not support the use of a name block.

In addition to a name block, you usually need a file access block (FAB) and a record access block (RAB). To perform file services, a FAB (and, if needed, extended attribute blocks [XABs]) must be present; to perform record services, a RAB must be present.

The following program shows how to use the LIB$FIND_FILE routine to locate the desired file, which the interactive user enters. Because LIB$FIND_FILE is used with the supplied arguments, the file specification may contain wildcard characters, a search list, and a search list that assumes the program will allow the use of "sticky" defaults, as in DCL command line parsing. The routine is called by the following VAX BASIC program USEROPEN option for the BASIC OPEN statement:

100 MAP (REC.1) SURNAME$ = 20%, REST$ = 60%
120 CLOSE #1%
130 END

The BASIC program allocates the control blocks before control is given to the USEROPEN routine; it also passes the address of the FAB as the first argument and the address of the RAB as the second argument. These arguments enable the VAX MACRO routine to obtain the control block addresses because the argument pointer points to the longword count of arguments, followed by the longword-length arguments. Because the VAX MACRO macros $FAB and $NAM are not used, access to the symbolic offset values defined for these control blocks is not available; thus, the $FABDEF, $NAMDEF and $RABDEF macros define these symbols for the USEROPEN routine.

In addition to locating the file using any valid file specification, the called routine also connects to the file requesting 15 global buffers (or as many global buffers as system resources permit). This routine is linked with the BASIC program to form the executable image. Example 5-2 shows the routine.

Example 5-2 Selecting the USEROPEN Option to Call a Routine

        .TITLE   LOCATE
        $FABDEF                              ; Define FAB symbols
        $RABDEF                              ; Define RAB symbols
IFILE:  .BLKB    80                          ; Input filespec
IFILED: .LONG    80                          ; Filespec descriptor
OFILED: .WORD    255                          ; Filespec descriptor
        .BYTE    DSC$K_DTYPE_T                ; Specify character text
        .BYTE    DSC$K_CLASS_D                ; Specify descriptor class
OFILE:  .LONG    0                            ; Address set by STR$GET1_DX
DFILED:  .ASCID   /.DAT/                      ; Default filespec descriptor
PROMPT: .ASCID   /Enter the filespec: /       ; User prompt
LOC_P:  .ASCID   /*** NOTE: Global buffers unavailable ***/  ;
NULL_P: .ASCID   / /                          ; Blank line prompt

ARGS:   .LONG    7                            ; 7 arguments
        .ADDRESS IFILED                       ; Input filespec
        .ADDRESS OFILED                       ; Output filespec
        .ADDRESS CTEXT                        ; Context
        .ADDRESS DFILED                       ; Default filespec
        .ADDRESS NULL                         ; No related filespec
        .ADDRESS STV_L                        ; STV field
        .ADDRESS UFLAGS                       ; User flags
CTEXT:  .LONG    0                            ; Context work area
NULL:   .LONG    0                            ; No related filespec
STV_L:  .BLKL    1                            ; STV status return area
UFLAGS: .BLKL    1                            ; User flags
LEN:    .WORD    255
        .ENTRY   LOCATE,^M<R6,R7>
        MOVL     4(AP),R6                     ; Move FAB address into R6
        MOVL     8(AP),R7                     ; Move RAB address into R7
        BISL2    #2,UFLAGS                    ; Set flag for sticky defaults
TERR:   PUSHAL   IFILED                       ; Get input length
        PUSHAL   PROMPT                       ; Prompt for input
        PUSHAL   IFILED                       ; Input descriptor
        CALLS    #3, G^LIB$GET_INPUT          ; Get input
        BLBC     R0,TERR                      ; Retry on error
        PUSHAL   OFILED                       ; Push descriptor address
        PUSHAL   LEN                          ; And length
        CALLS    #2, G^STR$GET1_DX            ; Allocate dynamic string
        BLBC     R0,ERR                       ; Branch on error
        CALLG    ARGS, G^LIB$FIND_FILE        ; Call RTL Find File Routine
        BLBC     R0,ERR                       ; Branch on error
        BRW      OPEN                         ; Skip on success
ERR:    PUSHL    STV_L                        ; Signal error status
        PUSHL    R0                           ; codes
        CALLS    #2, G^LIB$SIGNAL             ; Display error
        BRW      TERR                         ; Reenter filespec on error
        PUSHAL   OFILED                       ; Display filespec
        CALLS    #1, G^LIB$PUT_OUTPUT         ; on screen
        MOVL     OFILE,R10                    ; Move filespec address to R10
        $FAB_STORE FAB=R6,FNA=(R10),FAC=GET,-
         FNS=OFILED,SHR=<GET,MSE>             ; Set read-sharing global buffer
        $OPEN    FAB=R6                       ; Open the file
        BLBS     R0,CONNECT                   ; Branch on success
        PUSHL    FAB$L_STV(R6)                ; Push STV and STS in reverse
        PUSHL    FAB$L_STS(R6)                ; order on stack to
        CALLS    #2, G^LIB$STOP               ; Signal error and stop
; This block of code attempts to Connect with global buffers if possible
; and uses local buffers if global buffer resources are not available.
; Because the global buffer value is set between the Open and Connect,
; all defaults are overwritten.
        MOVL     #15,R9                       ; R9 contains global buffer count
        BRB      RETRY                        ; Skip local buffer handling
LOCAL:  MOVL     #0,R9                        ; Turn off global buffers
        $RAB_STORE RAB=R7,MBF=#6              ; Request 6 local buffers
        PUSHAL   LOC_P                        ; Inform user
        CALLS    #1, G^LIB$PUT_OUTPUT         ; No global buffers
RETRY:  $FAB_STORE FAB=R6,GBC=R9              ; Override default global buffer
        $CONNECT RAB=R7                       ; Connect the record stream
        BLBC     R0,RERR                      ; Branch on error
        BRW      DONE                         ; On success, return
RERR:   CMPL     R0,#RMS$_CRMP                ; Test if too many global buffers
        BNEQ     CERR                         ; Quit if other error
        CMPL     #4,R9                        ; Test if too few global buffers
        BLSS     LOCAL                        ; Use local buffers
        SUBL2    #3,R9                        ; Decrement R9 by 3
        BRW      RETRY                        ; Attempt Connect again
        PUSHL   RAB$L_STV(R7)                 ; Push STV and STS in reverse
        PUSHL   RAB$L_STS(R7)                 ; order on stack to
        CALLS   #2, G^LIB$STOP                ; Signal and end on error
DONE:   RET                                   ; Return to main program

Example 5-2 also shows the proper way to signal errors. The RAB$L_STS (completion status) field and the RAB$L_STV (additional status values) field of the FAB or RAB are used so that secondary completion information is displayed, if appropriate, by the LIB$SIGNAL or LIB$STOP routines.

The VAX MACRO program shown in Example 5-3 invokes the Parse service, determines whether a wildcard character or search list is present, and conditionally branches to a sequence of instructions that invoke the Search service followed by the Open service. The resultant string is displayed after the file is opened.

For more information about the LIB$ routines, see the OpenVMS RTL Library (LIB$) Manual.

The next example program uses the $PARSE and $SEARCH functions, demonstrates the use of C language's fopen function, and shows how you can mix RMS calls and C I/O calls.

Example 5-3 uses cc$rms_fab and cc$rms_nam to define the $FAB and $NAM control blocks and specify the arguments for the Parse, and Search services.

The program shows how to preprocess a file specification using the Parse and Search services. First, the program prompts the user for an input file specification that may contain wildcard characters. The program then searches each file that matches the file specification for the specified text string.

Finally, the program outputs all records from the target files that contain the specified string.

Example 5-3 Using the Parse and Search Services

/* Using Parse and Search Services */
#include <stdio.h>
#include <ssdef.h>
#include <stsdef.h>
#include <string.h>
#include <rms.h>
#include <starlet.h>

#define MAXLINE 256

static int rms_status;  /* RMS status variable */
static char ibuf[MAXLINE],  /* input buffer */
  obuf[MAXLINE],  /* output buffer */
  fbuf[MAXLINE],  /* filename buffer */
  xbuf[MAXLINE];  /* expanded filename buffer */
struct FAB filfab;   /* FAB for $PARSE and $SEARCH */
struct NAM filnam;   /* NAM for $PARSE and $SEARCH */
void init()    /* Initialize RMS structures */
 filfab = cc$rms_fab;  /* Get a FAB */
 filfab.fab$l_fna = ibuf; /* Parse filename from IBUF */
 filfab.fab$b_fac = FAB$M_GET; /* Only allow $GETs */
 filfab.fab$l_fop = FAB$M_NAM; /* Use the NAM block for filename */
 filfab.fab$l_nam = &filnam; /* -> NAM block */

 filnam = cc$rms_nam;  /* Get a NAM block */
 filnam.nam$l_esa = xbuf; /* -> Expanded filespec buffer */
 filnam.nam$b_ess = 255;  /* Expanded filespec buffer length */
 filnam.nam$l_rsa = fbuf;        /* -> Resultant filespec buffer */
 filnam.nam$b_rss = 255;         /* Resultant filespec buffer length */
 auto FILE *fil;  /* File pointer for file functions */
 auto int i;  /* Generic loop variable */

 init();    /* Initialize RMS structures */

 /* Get filespec to search */
 fputs("File: ", stdout);
 if (!gets(ibuf)) return;

 /* Validate filespec */
 filfab.fab$b_fns = strlen(ibuf);
 if (((rms_status = sys$parse(&filfab)) & STS$M_SUCCESS) == 0)
  return (rms_status);

 /* Get search string */
 fputs("String: ", stdout);
 if (!gets(ibuf)) return;
 /* Loop for all files matching filespec */
 while ((rms_status = sys$search(&filfab)) & STS$M_SUCCESS)
  /* Output a row of asterisks, the filename,
     and other row of asterisks */
  for (i = 0; i < 80; i++)
   obuf[i] = '*';
  obuf[80] = '\0';
  fbuf[filnam.nam$b_rsl] = '\0'; /* Add <NUL> terminator */
  if (fil = fopen(fbuf, "r")) /* Try to open the file */
   /* Process the file... */
   while (fgets(obuf, MAXLINE, fil))
    if (strstr(obuf, ibuf)) fputs(obuf, stdout);
   fclose(fil);  /* Done with this file */
  putchar('\f');   /* Print <FF> between files */
 if ((rms_status == RMS$_FNF) || (rms_status == RMS$_NMF))
  rms_status = SS$_NORMAL; /* Handle expected errors */


Previous Next Contents Index