How to Port vxVistA to GT.M


            This document provides step-by-step guidance for porting Document Storage System’s open-source vxVistA from Caché to GT.M.  This document will refer to other published instructions for steps that are described in detail elsewhere.

            The process of porting vxVistA from Caché to GT.M will consist of four main parts: 1) Download and install vxVistA to a Caché environment, 2) Export vxVistA routines and globals from Caché in a format suitable for import to GT.M, 3) Import vxVistA routines and globals to a GT.M database, and 4) make necessary configuration changes within vxVistA to enable it to function in the GT.M environment.


Part 1 – Install vxVistA to Caché


1.      Download vxVistA from to a convenient location on your computer.

2.      Extract files from the downloaded zip, and …

3.      Follow the instructions in the document, “simple_vxVistA 2010.1 Open Source Setup and Installation Guide.pdf” to copy the vxVistA cache.dat database file, and install it in Caché.


Part 2 – Export vxVistA routines and globals from Caché to host files


4.      In order to export routines and globals from the vxVistA Caché database, you will need to create a folder to receive the exported routines and globals.  A good idea is to create a parent folder, say “vxVistA-2010.1” and within that folder create subfolders named ‘r’ for routines and ‘g’ for globals, for example:

5.      Next you will access the VOS namespace, created in the step 3, at the “programmer prompt.”  To do this, right click the Caché cube icon in the Windows system tray, and choose Terminal:

This will open a telnet-like Window in the Caché USER namespace.  Change to the VOS namespace by entering ZN “VOS”:

6.      You are now ready to export routines (programs) and almost ready to export globals (vxVistA data files).  First, routines.  The Caché routine output utility ^%RO is compatible with GT.M’s routine import utility ^%RI, so this step is simple.  From the VOS> programmer prompt run the routine output utility and select all routines, using the ‘*’ wildcard, as illustrated below.  Be patient, after pressing <Enter> at the second “Routine(s)” prompt.  Assembling the list of routines to export may take some time.

After you accept the “No” default at the “Printer Format?” prompt, Caché will display routine names, as they are exported.

7.      Verify that the file was written to the ‘r’ sub-folder (or whatever name you selected for this folder).  The file size is approximately 95 MB.  We will convert the file to Unix/Linux format in a subsequent step.

8.      To export globals we will use a custom convenience routine that includes within it a list of vxVistA global names.  This routine generates a separate file for each global, in a format compatible for import to GT.M.  However, this utility routine is not part of vxVistA and must first be downloaded and then imported to the VOS namespace.  Just as you downloaded vxVistA in step 1, download SISZWR-vxVistA.RO to a convenient location on your computer.

9.      From the VOS programmer prompt, use the Caché routine import utility ^%RI to load the routine from the location where you saved it.  Note that the path on your computer may differ from the one in the illustration:

10.  This step uses the SISZWR routine to export globals to the ‘g’ sub-folder, or an appropriate location.  From the programmer prompt, carefully enter the following command, substituting the path on your computer where you want the exported globals to be stored.

Proofread this line before pressing <Enter>.  Note that no feedback will be displayed for this command in the VOS Terminal window.  However, if you open the ‘g’ sub-folder you will see many files being created, one for each global.  Some files are large, and the globals containing them take a significant time to export, for example the Lexicon EXPRESSIONS file in the ^LEX global.  Be patient.  When all globals have been written, the VOS> prompt will redisplay.  At this point, the ‘g’ sub-folder should contain 397 files (items).

11.  This completes the Caché export steps.  You may close the Caché Terminal window by typing ‘H’ for HALT, followed by <Enter> at the programmer prompt:


Part 3 – Import vxVistA routines and globals to GT.M


12.  If you have not yet installed GT.M, download and install the latest version from

13.  Create a Linux user for vxVistA.  Use all lowercase characters for the username.  We will create folders under this user’s login folder, to contain the GT.M database, and vxVistA files.

14.  Login as the vxVistA user.  In the user’s login folder, make a directory to contain the database, etc.  Choose a meaningful name, for example, the vxVistA version ID.

15.  Use FTP or SCP or some other means to copy the ‘g’ and ‘r’ folders containing the exported globals and routines from the computer where Caché is installed to the vxVistA user’s database directory, i.e., the directory that was created in the preceding step.

This copy may take a little while, depending on the speed of your network.  When finished you may check the contents of the g and r target folders to be sure that the transferred files are there.

16.  The global *.zwr files are text files, where each record terminates with ASCII 10 (linefeed) only.  In other words, they are in Linux text format.  However, the large routine output file, containing all vxVistA routines, is in Windows text format.  There are many ways to convert this file to Linux text format.  The following illustration uses Perl.  Change to the r directory and enter the following:

17.  In this step we create a backup of work completed in the preceding steps.  In the event that something goes awry in a subsequent step it will not be necessary to repeat all of the work.  Begin by changing the directory to the vxVistA user’s login directory (parent of the 2010.1 folder).  Then create a tar archive of the 2010.1 folder, its subfolders and their contents.  When complete, compress the archive using gzip.

The backup file vxVistA.tar.gz (or a substitute name of your choice) should be approximately 295 MB in size.

It would be prudent to copy this file to a USB key or network drive for safekeeping.

18.  The next few steps will create a GT.M database and import the vxVistA globals to that database.  First, set a few environment variables manually.  (Anticipate being logged-in to the vxVistA user account for some time.)

If you logout from the vxVistA user account before completing the steps in this section, be sure to reset the environment variables, after login.  In other words, repeat this step after a logout-login sequence.

19.  Create a global directory file, using the GT.M utility GDE.

You may wish to verify that the directory file exists in the 2010.1 folder.

20.  Next create the database itself, and adjust parameters, using the GT.M mupip utility.

The 2010.1 folder should now contain two files named database.dat and database.gld, in addition to the ‘g’ and ‘r’ sub-folders.

21.  Navigate to the ‘g’ sub-folder and create a sub-folder within ‘g’ named ‘q’ (for quarantine).  Move the YTT.zwr file to sub-folder ‘q’.  Global ^YTT includes subscripts (keys) whose lengths exceed the maximum length allowed by the MUMPS standard.  If imported to the GT.M database, these keys could cause a database integrity issue.

While still in the ‘g’ sub-folder, proceed to the next step.

22.  This step will import vxVistA globals from *.zwr files to the newly created GT.M database.  Each file corresponds to a different global.

After you have entered the command line shown in the above illustration, mupip will echo information about each global, as it is imported to the database.  As previously noted for the export step, some globals are large and require time to load.  Do not be alarmed by long pauses.  The last global to load is %Z.

23.  This step will import vxVistA routines from the allRoutines.RO file.  However, routines are not themselves loaded into the database file, but are extracted as <routine name>.m files to the $gtmroutines directory.  This step has several sub-parts.  First, change the directory back to the login folder (parent of 2010.1).  Next, invoke GT.M in direct mode (second line in the illustration below).  Then invoke the GT.M import utility routine ^%RI.  Answer the prompts, as illustrated below.  When specifying the output directory, be sure to include the final “/” character.  Omitting this character will cause the import to fail.  GT.M will display routine names as they are being extracted.  When finished enter the H (halt) command to exit direct mode.

24.  At this point the ‘r’ directory contains more than 25,000 source routines, stored as individual files, each with the .m extension.  GT.M compiles these source routines to an object code form, for efficiency of execution.  The object routines will have the .o extension.  For convenience, and to avoid unpleasant compile errors when routines are first referenced for execution by GT.M, in this step we will pre-compile the 25,000+ routines that were extracted in the preceding step.

First change directory to the 2010.1/r folder.  Then enter the command line shown in the following illustration.  Anticipate the display of many compile errors.  This is normal.

25.  This section, which created a GT.M database for vxVistA, and imported routines and globals, is complete.  In the next section, vxVistA will be configured and adapted for the GT.M environment.  At this point you may wish to make a convenience backup, to include the GT.M database and routine files.  This step is optional.


Part 4 – Configuring vxVistA and vxCPRS for GT.M


26.  Before beginning the configuration it is necessary to address a minor “catch 22” or “chicken and egg” problem.  The VistA Kernel setup program relies upon another program, which happens to be one of the ones that it sets up.  Thus, it cannot create the program, or any of the others that it creates, unless the program in question is available for use by the setup program.  If this does not make sense, don’t ask why, just perform the following steps.  First navigate to the ‘r’ directory, if not already there; then copy routine ZOSVGUX.m to _ZOSV.m and compile the latter, as illustrated below.

27.  This step may be regarded as an interpolation for convenience.  In the vxVistA login directory, create a script that defines environment variables and another script that connects to GT.M in direct mode, referencing the vxVistA environment variables.  This will eliminate the need to reestablish environment variables on each login, although this could also be done in the vxVistA user’s login profile.  Use an editor to create a file named vos-env.  The file’s contents will be as listed in the illustration below.  After creating the file, make it executable (chmod command).  Similarly create the vos file (stands for vxVistA open-source), with the contents shown below.  Make it executable also.

Test the vos script as follows:

28.  Now to the first “real” vxVistA configuration step.  Connect to GT.M using the convenience script ./vos and run the Kernel setup routine ^ZTMGRSET, as illustrated below.  Some key responses are highlighted.  Enter the two-part value VOS,VOS for the MANAGER’S and PRODUCTION UCI,VOLUME SET prompts.  In other words, do not accept the single part VOS default answer at these prompts.

Note highlighted responses.  System defaults to ‘3’ (the export environment).  Change this value to ‘8’.  Near the end, answer YES to the “Want to rename the FileMan routines” prompt.  When finished type ‘H’ to halt from MUMPS.

29.  The %Z* routines created in the preceding step, as well as %XUCI, have not been compiled.  Therefore, this step will compile them.  Navigate to the 2010.1/r sub-directory, and enter the commands shown below.  Once again, do not be alarmed to see more than a few compile errors.  These routines contain platform-specific code.  However, code for platforms other than GT.M will not ordinarily be reached during execution in the GT.M context.

30.  At this point, it is fair to test a couple of things, to confirm that the steps performed thus far have accomplished something.  We will run the main Kernel option driver, and then Fileman.  However, we will not make any substantial changes to the database in this step.  To run the option driver, SET DUZ=1 (user=1), then DO ^XUP.  To run Fileman, DO Q^DI and then enter ‘?’ to display Fileman’s main options.

31.  It may go without saying that if your test results do not correspond to those shown above, it is necessary to stop at this point, and troubleshoot the problem.  Unfortunately, such troubleshooting is beyond the scope of this “How to” document.  In the worst case, you can go back to the step where you last backed-up your work, e.g., step 17 or step 24, and redo steps from that point forward.

32.  This step is a little tricky, in that the value you will enter depends on your computer name.  It will not be the same value as shown in the illustration below.  First, at the GTM> prompt, enter the command shown in the first line of the illustration below.

The actual value displayed for variable Y will differ on your system.  We are interested in the fourth “^”-piece of this value, which in the above example is VOS:MP2800-U.  On your system, this piece will be VOS:<name of your computer>.  Whatever it is, use that value in place of MP2800-U when editing the BOX-VOLUME PAIR, as demonstrated below.  Include the VOS and colon, but substitute your computer name for the MP2800-U name.

Fileman (Q^DI) requires a user context.  If you have just started GT.M and have not yet established a user context, SET DUZ=1 before entering the DO Q^DI command.

33.  Soon we will start the vxVistA Task Manager to verify the preceding step.   However, before attempting to start Taskman, in the present step we modify two DEVICE definitions, substituting Linux / GT.M attributes, where appropriate, for Windows or Caché values.  First, the NULL device (bit bucket)… The NULL device, as exported from the Windows Caché implementation refers to the DOS / Windows device //./nul.  We will rename this device as WINDOWS NULL, and then rename the GTM-LINUX-NULL device to NULL.  This facilitates unambiguous lookup of the NULL device.

Next we address the HFS device.  HFS stands for “Host File System.”   This device is used by vxVistA to read or write to files on the host operating system.  Edit the HFS entry as illustrated below.

In the above example, press <Enter> when accepting the default value for a field.  At the QUEUING prompt, enter ^OPEN PARAMETERS to branch to the OPEN PARAMETERS field, skipping many irrelevant fields.  After entering the replacement value for this field, type ‘^’ to exit.

34.  When Taskman is started, it will automatically start several sub-tasks.  Two of these relate to starting TCP/IP listeners for vxCPRS and VistALink.  We do not want Taskman to attempt to start these listeners in GT.M.  Instead we will define an OS service listener for vxCPRS in a subsequent step.  Thus, at this point, the special queuing of these options will be removed.  While normally this would be done using a Taskman screen option, for expediency we use Fileman to remove special queuing of these options, as illustrated below.

35.  This step will attempt to start Taskman, and then check to verify that Taskman is running.  First, to start Taskman, use option XUTM RESTART, as shown below.

The above illustration assumes that the user context already exists.  If you have exited and re-entered GT.M before this step, type SET DUZ=1 DO ^XUP, as the first line.


Wait about 15 seconds before checking to see if Taskman has started.  DO ^XUP again, and Select OPTION NAME: XUTM ZTMON to examine the Taskman status.  This option displays a status screen that updates automatically.  To exit the monitor, type “^” and <Enter> at the UPDATE prompt.

The display shown above is normal.  Taskman is “current.” The status of the node we defined a few steps before this one VOS:MP2800-U (substitute your computer name) is RUN, and that node has an available sub-manager (last line).


36.  At this point it would be tempting to try a vxVistA user login.  However, that attempt would be certain to fail.  The reason is that vxVistA hashes login codes (access and verify codes), as well as electronic signature codes, using the VA VistA Kernel’s MD5 routines, which unfortunately rely upon one or more Caché Object Script functions that are not in standard MUMPS, and are not supported in GT.M.  It would be possible to disable this hash, or replace it with a different hash, but either of these options would require re-entering access and verify codes, and electronic signatures, for documented vxVistA users.  Much better is to compute the same hash, albeit in a different way.


vxVistA includes an “override” mechanism, by which one can substitute another computation in place of the default VA Kernel MD5 routines.  This mechanism is the file VFD IMPLEMENTATION-SPECIFIC API.  In this step, we will add an entry to this file, in order to hash access and verify codes (and electronic signatures), producing the same result as the vxVistA default hash.


Three sub-steps are required.  The first is trivially simple, the second nearly so, and the third will require care.  First, create a sub-directory of /tmp named xush (all lowercase).

Sub-step 2. Use an editor to create a script in the vxVistA user’s login directory /home/vxvista named xush (all lower case).  The script will have only two lines of text, as shown in the listing below.  When finished, be sure to make the script executable (chmod command).

The following example may be used to verify the above script:

Sub-step 3.  In this step we will create an entry in the VFD IMPLEMENTATION-SPECIFIC API file named ONE-WAY HASH.  The name is important because the entry is a pointer to the VFD SUPPORTED API file.  In the entry’s XECUTE field we will paste the long line of code below.  It would be possible to type in this line of code, but every quotation mark matters, making for a significant likelihood of error.  Therefore, it is recommended to copy the single line below, from the first to last character, and paste the line as the value of the XECUTE field.  Copy and paste the following:



N %,%0,F,Z S F="/tmp/xush/"_$J,%="zsystem ""echo "_X_" | /home/vxvista/xush > "_F_"""",%0="zsystem ""rm ""_F",Z="O F:READONLY:2 I  U F R X:2 C F" X %,Z,%0


The NOTES field is optional.  However if you do enter a note, use F1-E to exit and save the note (or F1-Q to exit without saving).  Press the F1 key and then the E key (or Q) successively.  Here is the full illustration.

Press F1, then E, to exit the NOTES editor.  Skip the final SITE ID prompt.  This step is complete.


37.  Page 2 of the document, “simple_vxVistA 2010.1 Open Source Setup and Installation Guide.pdf” (see Step 3 above) states that the vxVistA administrator login codes are Access: ADMIN123 and Verify: 123Admin! (where the latter is case-sensitive).  Use these codes to test the preceding step.  Login can only succeed if the codes are hashed identically to the stored hash in vxVistA.  For this test we will use the ^XUS routine and will simply halt at the first menu prompt, if successful.

The successful login illustrated above proves that the hash computed by the Linux md5sum, suitably wrapped, is the same as the stored vxVistA hash for the ADMIN user.  If you are an expert Linux / GT.M user, you may wish to improve or simplify the rather complex step 36.  For example, a pipe might be substituted in place of the scratch file /tmp/xush.  Keep in mind, however, that the XECUTE field code must satisfy Fileman’s ^DIM syntax checker.

38.  Why did step 37 use ^XUS, rather than ^ZU to test the first logon?  One answer is that routine ^ZTMGRSET does not file the platform-specific ^ZU routine.  Where is routine ^ZUGUX?  The answer to this question is that there is no ^ZUGUX.  Instead, routine ^ZUGTM supports the GT.M platform, whether under VMS or Unix / Linux.  In this step we copy routine ^ZUGTM to ^ZU and compile it.

39.  Before testing a login to vxVistA through ^ZU, we will create a script, to illustrate how user login might be tied to ^ZU.  Use an editor, and create a three-line script, with the contents shown below.  Once again, do not forget to make the script executable.

Now test login to vxVistA via the zu script.  Reminder: The access code is ADMIN123 and the verify code is 123Admin! (case-sensitive).

To exit from vxVistA type halt at the menu prompt.


40.  Similar to the way in which vxVistA computes a hash of access / verify codes etc., when a (TIU) document is signed, vxVistA stores an encrypted string that encodes a combination of the signature block and a checksum of the document itself.  Unlike the login codes hash, this encrypted string can be decrypted, and is decrypted whenever a document signature is displayed.

The algorithm used by vxVistA for document signature block encryption also relies upon non-standard language features that are not supported in GT.M.  However, because vxVistA (open-source) does not include any signed (TIU) documents, it is not necessary to implement the same encryption algorithm as vxVistA uses by default.  Thus, the problem of implementing an alternative invertible encryption for document signature blocks can be deferred.

For the present, we will override the default vxVistA document encryption, in order to avoid an error on signing a test document.  In this case, the override will be simply no encryption.  Instead of a long line of code, the XECUTE field for ENCRYPT STRING and DECRYPT STRING entries will have the value ‘Q’ for quit.  Create these entries in the VFD IMPLEMENTATION-SPECIFIC API file, using Fileman, as illustrated below.

41.  In the first few steps of part 3 of this document, we defined a directory structure to contain the vxVistA GT.M database and routines.  This structure is similar to VistA / GT.M community practice, but other structures are also possible, and in common use.  One such alternative stores object routines (.o files) in a separate directory from source routines (.m files).

In order to work independently of the platform, [vx]VistA uses various methods of invoking platform-specific code when needed.  Previous steps have addressed platform-specific VistA library (%Z*) routines, for example.  In this step we will modify another structure that implements platform-specific code for saving routines.

This code is located in the ZSAVE field of the GT.M(UNIX) entry of the MUMPS OPERATING SYSTEM file. Before modification, the code assumes that object routines are stored in a separate directory from source routines.  It will be necessary to modify this code for the simpler directory structure that we have created for vxVistA.  This will be the first use of Fileman’s ‘Replace-With’ editor.  Although the line of code to be edited is long, we will be changing only a short part of it, the following:

Replace $P($P($ZRO,")"),"(",2) With $P($ZRO," ")

The following example illustrates the entire Fileman editing session, including the critical ‘Replace-With’ part:

Note added in revision:  If Fileman is re-initialized after modifying the ZSAVE code as described in the present step, the initialization process will replace modified ZSAVE code with the original.  In Fileman version 22.0 (ca. 2012), the original (default) code may be found in routine ^DINIT21.

42.  vxCPRS – At last!  As noted in a previous step, we will configure an OS service to accept vxCPRS connections.  Details may vary between different Linux flavors.  However, concepts are generally equivalent.  For an introduction to Linux sockets, with examples, a useful tutorial may be found at


First, create yet another script in the vxVistA user’s login directory.  The name doesn’t much matter.  However, call it rpcb-9201 for “remote procedure call broker – port 9201.”  Use the editor of your choice and enter the script shown in the listing below.  Do not forget to make it executable.

It is possible to test this script, independently of the service that will run it.  To do so, execute the script, then press CTRL-C to reach the GTM> prompt.  At this point, enter the ‘zwrite’ command to examine the symbol table.  Then enter ‘h’ halt.  The following illustration includes only the first few lines of the symbol table.

43.  As previously noted, there are several different ways to define and start a service.  This step will illustrate one method, using the xinetd super-server.  You will probably not be able to perform this step from the vxVistA login context, as it requires super-user privileges.  Login as a user that can ‘sudo’ for this part.  For example –

If your Linux OS does not use xinetd, then identify an alternative way of establishing the vxVistA RPC Broker listening service.  In this example, we edit the xinetd.conf file to add the desired service.  The same might be accomplished by creating a separate script for the service in the /etc/xinetd.d directory.  In any case, the following illustrates the lines to be added to xinetd.conf (or as a separate script).

Finally, edit the /etc/services file, adding the following line:


44.  If you are using xinetd, as illustrated in the preceding step, restart the super-server.

After restarting, verify that the service is running.  For example, ‘netstat –l’ should include a line similar to the following in its display:


45.  If you have not already created a shortcut to the vxCPRS executable, as described in the “simple_vxVistA 2010.1 Open Source Setup and Installation Guide.pdf” document, do so at this time.  Edit the properties to specify the IP address (or host name) of your GT.M / vxVistA installation, port 9201.  In other words, replace the word LOCALHOST in the illustration on page 42 of the aforementioned document with the IP address or host name of your vxVistA server.  Apply or save this change.

Open the vxCPRS shortcut.  After a few seconds you should see the vxCPRS login form:

Enter the same codes that were used previously to test an interactive terminal login, ADMIN123 and 123Admin! (case-sensitive verify code).  If successful, the patient selection form will display on top of the vxCPRS cover sheet.

Select a patient, and click OK.  In the example below, Zztestpatient,One M was selected.

If you have left Taskman running (from the step that tested Taskman startup) the cover sheet display should look the same as the illustration above.



The following steps will be described in less detail than previous steps, under the assumption that experience gained from exercising configuration steps up to the successful launch of vxCPRS makes greater detail unnecessary.


Part 5 – Additional Configuration for TIU and BCMA


46.  Step number 40 explained that when a (TIU) document is signed, vxVistA stores an encrypted string that encodes a combination of the signature block and a checksum of the document itself, and that the encryption algorithm used by vxVistA relies upon one or more non-standard language features that are not implemented in GT.M.  The present step suggests how to substitute a different invertible encryption algorithm, one that uses only standard MUMPS and works the same in GT.M and Caché.


Note: This step has been temporarily removed, due to a conceptual flaw in the original suggestion.  An alternative suggestion may be substituted in the future.  Meanwhile, skip this step and continue with step 47.


47.  In this step we will address another usage of a non-standard language feature.  However, this is not a vxVistA-specific usage, but one that is found in the FOIA release of VistA itself.  A few VistA routines rely upon the two-parameter form of the MUMPS $QUERY function.  This form is supported in Caché but is not part of standard MUMPS and is not included in GT.M.  As a workaround, we will use an extrinsic function to simulate the two-parameter form of $QUERY.  If you are a MUMPS programmer you may wish to create your own substitute function for $QUERY.  The one given here uses $QSUBSCRIPT, and requires GT.M version 5.4-002B or greater.


Download the routine SISQSIM in either Caché routine save format or in GT.M source routine format.  Use the GT.M utility ^%RI, as described in previous step number 23, to import routine SISQSIM from the SISQSIM.RO file.  Alternatively, simply copy the GT.M source format routine to the routines directory …2010.1/r/.   After importing or copying the routine, compile it.  Compiling the routine will display an error in a part of the code that is not reached in the GT.M context.

After compiling the routine, run the following test –

As indicated by the comment, this test takes a few minutes and, if successful, produces no output.  The test simulates reverse $QUERY through all nodes in the Fileman data dictionary global ^DD.


48.  This step will show how to identify VistA code that uses the two-parameter form of the $QUERY function, and will give an example of substituting the $$Q^SISQSIM extrinsic function that was loaded and tested in the preceding step.


First, an example… The line of code reproduced below includes a use of the two parameter form of the $QUERY function.  The context is an API related to Military Sexual Trauma (MST) information.  While GETSTAT^DGMSTAPI may not be needed or used in a non-VA implementation of VistA, this example serves to illustrate the $QUERY problem.

We will modify this reference to use the $$Q simulation in place of the intrinsic $QUERY function.  While the intrinsic function expects a local or global variable as the first parameter, the simulation needs instead the name of the variable.  Use any editor, vi for example, to edit the routine.  The illustration below shows the edit in VPE’s ..e editor. 

The replacement code shown in line 47 above calls $$Q^SISQSIM instead of $Q and wraps the global variable using the $NA (name) function.  This is the same process as will be used for replacing other usages of the two-parameter $QUERY.


It is important to keep track of VistA routines that have been modified, as these routines may be included in a future VistA patch.  If they are, then the modification must be revisited after installing the patch.  Therefore it is recommended to maintain a file of modified routines for possible future reference.


The obvious question that occurs is how to find such usages of the two-parameter $QUERY in VistA, in order to anticipate problems before they occur, i.e., before they result in application-level MUMPS errors.  To aid in this endeavor, we will import yet another utility routine.  Again the routine is provided in both Caché routine save and GT.M source formats.  Download, install and compile this routine, in the same way as the SISQSIM routine was installed above.  No compile errors are expected.


The next illustration shows how to use this utility to search a group of routines for a MUMPS pattern.  In this example we will search the BCMA routines (PSB*) for a pattern that could indicate a two-parameter $Q reference.

The illustration above omits the search output.  The output lists three routines, one of which is a false positive.  In other words, one of the routines includes code that matches the MUMPS pattern but is not a usage of the two-parameter $QUERY.  The two routines that do use the two-parameter form of $QUERY and the references themselves are shown below.

A few additional remarks may be warranted, in regard to the task of modifying these routines.  First, note that the variable PSBQRY is indirected in $QUERY parameter references.  This means that variable PSBQRY contains the name of the $Q parameter variable.  In other words, when substituting $$Q^SISQSIM, you would refer to variable PSBQRY itself, to pass the name, that is, $$Q^SISQSIM(PSBQRY,-1).  Second, note that not all references to variable PSBQRY in the above lines involve a $Q call.  For example, the reference to $E($P(PSBQRY,U,1),1,12) does not involve $QUERY, and therefore does not require modification.  Third, note that where more than one reference to the two-parameter form of $Q exists in the line of code (+128^PSBOMH1 and +79^PSBRPC2), one may wish to split the line for clarity.  However, substantial care is required, because lines with more than one $Q(…,-1) reference are within the scope of IF commands (the first commands in each line).  This scope must be preserved over any additional lines that are created to replace these lines.


Proceed to modify the PSB* routines identified above in the same way as was illustrated for routine DGMSTAPI at the beginning of this step.  Remember to record the modified routines for future reference.  Also, when this part of the configuration work is complete, it may be prudent to search for possible additional uses of the two-parameter $QUERY in other VistA applications.


49.  Next, anticipating a possible problem, we will define a couple of additional directories.  Step 36 created sub-directory xush in the /tmp folder.  By the way, if your flavor of Linux clears the /tmp folder on system boot, this feature should be disabled.  Configure startup to retain sub-directories of the /tmp directory on reboot.  Alternatively, create these temporary directories in a different path, one that is not cleared on reboot. 


Make two new sub-directories, for example, named /tmp/hfs and /tmp/psb.  Then use Fileman to name /tmp/hfs as the PRIMARY HFS DIRECTORY in the KERNEL SYSTEM PARAMETERS file.

Similarly use ^XPAREDIT to name /tmp/psb as the PSB HFS SCRATCH directory.

50.  We are now ready to test vxBCMA.  Locate the vxBCMA executable from the download and create a Windows shortcut to the program.  Configure the shortcut for the RPC Broker server and port in the same way as was described for vxCPRS in step 45.  Open the shortcut.  A vxBCMA splash screen will be displayed, followed by the standard VISTA Sign-on form.  Use the same logon codes as were used in previous steps, including the vxCPRS test step (45).


You may also receive a warning about a clock time discrepancy between the Windows client and Linux server.  Of course, the clocks should be synchronized.  However, for the purpose of this test, the warning may be ignored.  Next the Patient Lookup dialog appears.  In normal usage, vxBCMA expects the patient’s wristband to be scanned.  However, it is the same to type the patient ID in the text box, as shown.

Upon responding affirmatively to the patient confirmation (below), …

the vxBCMA main form will be displayed.  Note that patient ABC001 is the only inpatient in the 2010.1 database, as distributed.  If you have admitted other test patients, of course they may also be selected.

Display of the main vxBCMA form proves only that the application is runnable.  Changing to the Cover Sheet tab shows that this patient has no orders for display.  Therefore, it is not possible to demonstrate anything meaningful with vxBCMA until some current or recent inpatient medications orders have been processed for the patient.


Part 6 – Tools, HL7 and Beyond


51.  In step 48 we mentioned the possible use of VPE for editing a routine in vxVistA.  VPE is a popular programming shell for VistA that includes useful utilities for displaying and editing routines and globals, and for displaying the Fileman data dictionary.  The latest version may be downloaded from 

While VPE was pre-installed in the vxVistA environment, VPE %-routines and globals were not transported in this port of vxVistA to GT.M (steps 6 – 10).  Therefore, it is necessary to do a clean install of VPE to the VOS (GT.M) environment.  Download VPE MGR and PRD routine save sets from the above link.  The MSM version of these routine saves can be imported using the GT.M ^%RI utility.  After downloading the .MGR and .PRD files, convert them to Linux format, as was illustrated in configuration step 16.  Then import and compile them, as previously illustrated for other routine sets.  Follow the instructions given in ‘VPE_12_Read Me.txt’ to initialize VPE (DO ^ZVEMBLD and DO ^VEEMINIT).  Note that both initializations should be performed in the VOS account—there is no separate MGR account.

Step 41 explained how to modify ZSAVE code in the MUMPS OPERATING SYSTEM file for the GT.M(UNIX) entry.  The specific modification required depends upon the scheme used for storing vxVistA source and object routines.  If both source and object routines were stored in the same directory (../2010.1/r/), the modification given in step 41 will also work for VPE’s routine editor.

52.  We have reached the point where additional configuration of vxVistA under GT.M requires more detailed knowledge of vxVistA (or VistA) applications.  However, the methods illustrated in this preliminary configuration document should apply also to configuring other applications, such as VistA HL7.  For example, the rpcb-9201 script that was created in step 42 can serve as a pattern for making a similar HL7-in script.


vxVistA and FOIA VistA come pre-defined with one multi-listener logical link named LISTENER on port number 5340.

The convention for HL7 VistA listening ports is to use port 5000 for production and port 5025 for test.  However, to minimize the setup required, we will use 5340 as the HL7 listening port in this example.  Begin by creating a script.

Note the obvious similarity to the rpcb-9201 script.  Be sure to make the script executable.  After creating the script, create the corresponding service and add it to the services file.  These steps are analogous to what was done for the RPC Broker listener in step 43.  If you are using xinetd for these steps, then restart the super-server, when finished.


One last step for HL7… The LISTENER logical link, as distributed in FOIA and vxVistA refers to an address on the VA’s private network.  Use either HL7 Interface Developer Options … EL, or Fileman, to remove this address.

At this point vxVistA should be set to receive inbound HL7 messages via port 5340.  Configuring HL7 to process received messages is a non-trivial task, and falls beyond the scope of this ‘How to’ document.  However, you can verify that the infrastructure created in this step works properly, without setting up an application to process the received HL7 message.


If you are able to send an HL7 test message in to port 5340 using Mirth (or any message sending application) it will be possible to verify that the message was received and handed to vxVistA HL7.  Use Fileman to inquire to the HL7 MESSAGE ADMINISTRATION file (File 773).  Note that the ‘0 Entries’ warning is spurious.  VistA HL7 does not maintain the header of this file.  After sending the message, inquire for any message received TODAY.  Here is an example.

The second message in the above ‘choose’ list is the VistA-generated ACK.  Here are the details of the received message.

STATUS: ERROR was expected, as no application has been defined to process the received message.  However, the existence of this entry in the HL7 MESSAGE ADMINISTRATION file proves that the message was received in vxVistA.  Consult the relevant VistA documentation for additional information about HL7.


53.  The GT.M environment does not include certain built-in utilities that are familiar to Caché users, such as a System Status display.  Instead, the GT.M model relies on the underlying operating system, augmented by open source tools, for system administration, software development, and so forth.


A simple System Status utility that includes “Job Examine” and “Kill Job” functions is described in detail and available for download here.  This utility has been tested with the specific implementation of vxVistA under GT.M described in the present document.  See illustration below.






This completes the basic port of vxVistA to GT.M.  Additional work will be needed to set up other applications, such as VistALink, or to configure vxVistA for use as a working EMR in a real Health Care setting.


Note that Document Storage Systems, Inc. does not presently support vxVistA under the GT.M platform (July 2011).  Therefore, additional support can be expected only on a voluntary basis from the community of users.


The author makes no claim as to the accuracy or completeness of the information contained in this document.  In no event will the author be liable for any damages, lost effort, inability to deploy the application, or anything else relating to a decision to use the information in this document.



vxVistA 2013.0


A massively patched and updated version of vxVistA (open-source) was released in February 2014—see This release includes vxGroupNotes, vxPatientPicture, and vxVitals, as well as vxBCMA and vxCPRS.


The procedure for porting vxVistA 2013.0 to the GT.M environment is analogous to porting the 2010.1 version, as was described in the preceding 50+ steps. Of course, one should choose version-appropriate names for the database directory, and script files, replacing 2010.1 with 2013.0, and VOS with V13, and so forth.


In step 17 of the 2010.1 port we saved a backup of work. A similar archive of the 2013.0 port may be downloaded from here. This archive includes the vxVistA 2013.0 routines in GT.M %RO format (Restore using ^%RI). The archive also includes the 2013.0 globals as one large mupip extract, and separately the ^YTT global in zwr format (Restore using mupip). The latter global has unusually large keys. However, recent versions of GT.M will accommodate key lengths of up to 1019 characters (K. S. Bhaskar, private communication).


The vxVistA 2013.0 download (from includes complete documentation for installation and configuration of the database and associated GUI applications.  The following notes suggest ways of avoiding possible points of failure, when implementing vxVistA 2013.0 under GT.M.


1.      The patched version of Taskman that is distributed with vxVistA 2013.0 contains a non-standard construct that is not allowed by GT.M (but allowed by Caché, and thus not noticed in the Caché environment). A lock that was acquired prior to the start of a transaction is released after the start of the transaction and before it has been committed. The offending code is found in routine ^%ZTLOAD1. To correct this, the order of committing the transaction and releasing the lock must be inverted.

2.      The second suggested change also involves Taskman. However, in this case it is a vxVistA-specific patch that requires changing. Under some circumstances, a null-subscript error can occur. This is prevented by testing ZTIO and quitting if the variable is empty, in effect reinstating the original version of this test.

3.      The vxVistA 2013.0 database includes three test patients with data.  These test patients have “alternate IDs” for an INSTITUTION different than the one configured. It is recommended to duplicate these alternate IDs for the INSTITUTION entry, and to mark the added entries as DEFAULT alternate IDs.


The same disclaimer applies to these 2013.0 notes as for the 2010.1 steps (see note following step 53 above).


IAQ – Infrequently Asked Questions


This section presents questions that might have been asked, had this project generated sufficient interest.


1.       Step 28 describes how to run the Kernel setup routine ^ZTMGRSET.  Is it necessary to initialize Fileman also?

Yes, Fileman should be initialized (DO ^DINIT).  Specify the type of MUMPS as GT.M(UNIX):

Specifying GT.M(UNIX) as the type of MUMPS system causes Fileman to set the ^DD(“OS”) node to the internal entry number of the GT.M(UNIX) entry in the MUMPS OPERATING SYSTEM file (IEN=19).  Fileman needs the correct MUMPS type value when saving compiled templates.

See also the note at the end of step 41 of this document, explaining that initializing Fileman replaces the contents of MUMPS OPERATING SYSTEM file entries, including the ZSAVE code, which may have been modified.

2.       vxVistA includes a few routines that have names greater than the SACC standard 8 characters in length.  How can one view or edit these routines in VPE?


VPE includes checks for both routine name length and line tag length.  To view or edit a routine that has a long name, it is necessary first to modify VPE, changing the maximum length allowed from 8 to 16 characters.  Edit, save, and compile the following five VPE routines, as illustrated.