OpenVMS Demos: Programmer's Corner (new version)

VMS VAX (Virtual Address eXtension)
AXP (Alpha - Almost eXactly PRISM?)
IPF (Itanium Processor Family)
VSI (x86-64 - VMS Software Inc.)

This entire sub-domain is a private effort of free information.
There are no cookies, no advertisements, and nothing is for sale.

OpenVMS Resources (non-code) can be found here

  1. The programs and information presented on this web site are intended for educational use only for OpenVMS application developers.
  2. The programs and information presented on this web site are provided free of charge.
  3. The programs and information presented on this web site are presented to you as-is. I will not be held responsible in any way if they damage your computer system, business or organization (sounds like the warning from a Microsoft shrink-wrap seal, eh?)
  4. To the best of my knowledge, the programs presented on this web site compile, link and run properly. Please let me know if they don't work and I will attempt to fix them as soon as I find the time (I only support this stuff in my spare time).
  5. Is this text too small? You have two options:
    1. hold down the CTRL key while rolling the mouse wheel (zoom-in, zoom-out)
    2. use your keyboard like so:
      • hit: CTRL with "-" key to zoom smaller
      • hit: CTRL with "+" key to zoom larger
      • hit: CTRL with zero key to reset zoom
Index / Quick Navigation

OpenVMS Source Code (presented in HTML format)


OpenVMS C/C++

Hybrid Programming

DCL (Digital Control Language)

Macro Assembler

OpenVMS Programming

Updated: 2015-08-12

OpenVMS Source Code (presented in HTML format)

Presented in HTML format so:

How my source code pages were webified

My demo programs were converted to HTML pages by running my source code through this VMS-BASIC-based utility:

What does it do? For the most part, it converts certain "HTML sensitive" characters into "HTML entities" (meta data) like so:

Original Character HTML Entities
& &
< &lt;
> &gt;

The utility also inserts <pre> before my first line and appends </pre> after my last line in order to preserve spaces and tabs. Optionally, this utility can build a complete web page.

OpenVMS demo source code (old)

Some unconverted stuff (mostly RDB related sources) can still be found here in zipped format:



General Info Link: OpenVMS Notes: VMS-BASIC (coding techniques)

File I/O Demos

Technology Program Notes
RMS   Record Management Services for OpenVMS (ISAM)
  rms_sequential_demo.bas shows how to manipulate sequential RMS files (with BASIC terminal i/o calls)
  rms_relative_demo.bas shows how to manipulate relative RMS files (with BASIC terminal i/o calls)
  rms_indexed_demo.bas shows how to manipulate indexed RMS files (with BASIC terminal i/o calls)
  rms_indexed_demo_fms.bas shows how to manipulate indexed RMS files (with a few FMS i/o calls)

FMS (Forms Management System) Notes:

  • in the early VAX/VMS days, developers were encouraged to insert their various FMS forms (name1.frm) into a developer-created "forms library" (name.flb). During image activation, the program would call FDV$LOPEN to open the library, FDV$LOAD to fetch the forms into various workspace buffers, then FDV$LCLOS to close the library connection. In those days I went to great lengths to reduce the cost of image activations. One solution was to bypass the form library by creating a binary version of each form then linking them to the executable. This demo shows you how to do this.
  • There are ~ 66 FMS functions and you can read more about them by downloading manuals from here:
  rms_test_fsp.bas a little hacking with the FSP$ function (only meant to support older BASIC-PLUS-2 programs. Newer code should to trial opens using USEROPEN)
  rms_test_useropen.bas do a trial file-open using a USEROPEN function
  • an intermediate version includes a hack to allow inclusion of XABSUM and XABKEY (this last one is for inspecting keys a.k.a. indexes)
  • recently added code to include XAMPRO (to inspect protection bits)
  • this program works in two modes:
    • simple-and-safe:
      • simply tack my pointer onto the existing FAB:XAB pointer (overwriting what was their previously)
      • do my thing
      • restore original pointer before exiting useropen
    • complex-and-dangerous:
      • start at FAB:XAB then scan the linked list until you hit a zero. Then use a home-grown POKE routine to tack my list onto the end of the existing list
      • do my thing
      • restore original pointer before exiting useropen
  sys_file_io_demo.bas doing file i/o in BASIC without using BASIC's file i/o routines
  read_sysuaf.bas directly reading SYSUAF records for audit purposes only (you need lots of privs just to open SYSUAF.DAT)
RDB   a.k.a. Oracle-RDB (Relational Data Base)
    you can find the original 43-file zipped package here
More information: OpenVMS Notes: Oracle-RDB
MariaDB   An alternate fork of MySQL
  C-sources: MariaDB caveat: You would need a wrapper to use these from BASIC but I think it is possible.
  RMS Export Tools:
our current system consists of 70+ BASIC programs reading/writing 150+ RMS indexed files. In order for us to do a parallel (RMS=production, MySQL=daily snapshot) operation over the next 12 months, we needed a semi-autonomous method of tool generation. These three BASIC programs read record definition declarations in our BASIC source code then generate:
  • 99% complete BASIC programs to extract data from RMS files then write it to CSV files (usually tab delimited)
    • you need to edit one line before compiling (the input file name)
    • generic open/read your RMS files (bypasses your basic indexes/keys)
    • this tool is preferable to opening up your source code to insert customized export routines
    • once built, there is no need to do this again unless the RMS file format changes; which means these can be called from batch
  • 99% complete SQL scripts to create the tables then import the data from CSV files
    • since my tool does not (yet) analyze the OPEN statements, you will need to insert SQL statements to create constraints, indexes and keys, etc.
    • CAVEAT: you could modify the table creation statements before the import but this would cause the import to be hundreds of times slower (lots of recursion while it maintains each index AND you could still end up with a lop sided index if the inserted data was already ordered). All large imports should always be indexless and constraintless; you tack them on as a finishing step.
    • I placed all my post-import SQL statements in a second script which won't be overwritten by the tool

I/P Stack Demos (this code is written in BASIC; check out my C/C++ demos farther down this page)

Stack Programs Notes
  HP's official IP stack for OpenVMS
1. versions 5.0 and greater produce variables prefixed with "TCPIP"
2. lower versions produce variables prefixed with "UCX" ("UNIX Communications Extensions" or "Ultrix Communications Extensions")
a) Synchronous (qiow) TCP client demo :: employs http to retrieve a web page
b) Synchronous (qiow) TCP client demo :: adds support for gethostbyname
c) Asynchronous (qio) TCP client demo :: employs programmable timers
d) Same as "c" except my TCP routines have been moved into external functions
e) Same as "d" but with NVT support for TELNET
 1) all these programs employ VMS System Services rather than the Sockets API
2) changing one INCLUDE (external reference) will allow them to work with any stack
  tcpip$tcp_sa_client_qio_basic.bas stand-alone client demo (telnet to another system, log in, run a program, log out)
this program works but is still under development (but probably wont be finished)
  get_host_by_name_qio.bas domain name lookup from BASIC (also contains a few hacking tools)
  sff_demo_basic.bas demos function tcpip$send_from_file() which is a nifty way to send SMTP messages to your own stack without opening a connection to port #25
MultiNet   1) a third-party stack from Process Software (supports IPv4 and IPv6)
2) more feature-rich than TCPIP Services for OpenVMS from HP
TCPware   1) a third-party stack from Process Software (only supports IPv4)
2) this was the only IP Stack for VMS in the 1980s and first half of the 1990s
3) the Telnet API and FTP API provide a solution midway between Sockets and System Services
  TCPware_telnet_sample.bas Employs TCPware's TELNET API to demo CHARGEN, ECHO, HTTP, and TELNET. Also contains a minimal NVT handshake necessary for TELNETing to UNIX systems (Solaris will not let you connect unless you can provide a TERM TYPE via IAC WILL-WONT-DO-DONT; makes me wonder if this isn't some sort of simplistic anti-hacking effort) 
  TCPware_pop3_demo.bas Employs TCPware's TELNET API to demo connecting to a POP3 server to retrieve email
  TCPware_smtp_demo.bas Employs TCPware's TELNET API to demo connecting to an SMTP server to send email
  TCPware_ftp_sample.bas Employs their FTP API to demo doing FTP from within a BASIC executable

Web Demos

Topic Programs Notes
Glued  Example
  1. drop this DCL script into any one of your apache user-accessible scripts directories (I use "[.scripts]")
  2. rename the file to match the URL you wish to use. For example, if the link is "/demo123" then rename the file to ""
  3. modify the script to run this next program called "read_html_apache.exe". It will read/decode the received HTML page then create DCL symbols representing the contents of HTML objects on the web page.
  4. if the program ran properly, now run your desired program which will read the DCL symbols then do whatever you want
  5. use a browser to test your application like so:
  read_html_apache.bas Have the script above run this program which will:
  1. read data sent by the browser to the web server
  2. decode the HTML page
  3.  create DCL symbols representing HTML data contents of HTML objects on the web page.
apache_demo.bas This stand-alone application does not require any glue (DCL script). You could do one of the following:
  1. create a one-line DCL script which does nothing other than run your executable program
  2. drop the executable program directly into the Apache scripts directory.
Password  Change
  • CGI Glue
    • can be used standalone (does not use CGI glue)
    • can be used not standalone (see Apache Glued Example above)
  • can hook into an external database (RMS in my case) to validate users
  • demos how a small amount of JavaScript (embedded in the BASIC source) can be used to pre-validate the HTML form then enabling/disabling the submit button
Upload  Demo coming Got this working in production but it needs to be cleaned up before publishing.
SOAP Demo coming Since all my SOAP services are written in C (via gSOAP) or Java (via AXIS or AXIS2 running on Tomcat), I may publish a little BASIC program used to send SOAP test cases (messages) to a published SOAP service.
AJAX Demo coming

but here is a little taste of only the JavaScript file: ajax_vdsl_port_mtce.js

  • AJAX (Asynchronous JavaScript and XML) is a very cool, although poorly understood, client-server technology used in conjunction with DOM-compliant browsers.
  • AJAX allows a browser to fire JavaScript function XMLHttpRequest to issue an HTML request on a secondary channel behind the current web page. The response comes back then JavaScript can be programmed to inject data, inject HTML code, or anything you want, into the DOM-compliant web page.
  • AJAX can send back ANY text document. Plain, XML, HTML, whatever.
  • Back in the day, I wrote many VMS BASIC applications which employed FMS (form management system) forms on character cell terminals like so:
    Desired Action BASIC Code
    display a form call fdv$disp( fname$ )
    populate a form (field-by-field) call fdv$put( last_name$, "f$last_name" )
    populate a form (all at once) call fdv$putal( whole_form$ )
    read a form (field-by-field) call fdv$get( last_name$, terminator%, "f$last_name" )
  • I recently moved a BASIC application from FMS on VT320 to HTML/JAXA on browser by first creating a static web page which contains an HTML version of my FMS form (the FMS field name became the "id" of the HTML input object). My app first loads the static web page then issues (based upon user input) AJAX transactions requesting tagged data. Some of my scripts process the tagged data then:
    populate INPUT objects via:
        document.getElementById(fn).value = fd
    or populate DIV objects via:
        document.getElementById(fn).innerHTML = fd
        fn = field name
        fd = field data

Data conversion / manipulation

Programs Notes
ebcdic_ascii.bas convert EBCDIC to ASCII
iso_8859_to_ascii.bas convert 2-octect unicode to 8-bit characters then (optionally) map the result to 7-bit characters
base64_decode.bas base64 decode
sort_demo.bas calling VMS sort routines (hey, sometimes it is best to leave it to the experts)

Miscellaneous Stuff

Topic Programs Notes
Command Line foreign_cmd.bas allows a BASIC program to read DCL command-line parameters like "C" on UNIX
DCL symbols dcl_symbols.bas reading DCL symbols from BASIC
DECnet client (start a remote server then send it some messages)
DECnet server (echo messages back to client)
Device Scan device_scan_demo.bas scan some/all devices on the system
Key Exchange Demo
diffie_hellman_demo.bas Diffie-Hellman Key Exchange Demo (limited to 64-bit math)
Displaying System errors display_system_error.bas can translate any system error number into the associated text message. This program is no longer required since modern OpenVMS versions can do this for you from the DCL prompt.
Health Monitor health_check.bas
like a super watchdog except this programs makes sure certain programs and batch job are present
sample data file to program 'health check'
Lock Demos (CEF) cef_lock_demo.bas CEF (Common Event Flag) Lock Demo
Lock Demos (DLM) dlm_demo_100.bas DLM (Distributed Lock Manager)
creates a null lock then synchronously converts it to more restrictive forms
  dlm_demo_101.bas creates a null lock then synchronously converts it to more restrictive forms
  dlm_demo_102.bas asynchronously requests an exclusive lock then polls DLM to see if it was granted
  dlm_demo_103.bas asynchronously requests an exclusive lock, then arms a timer, then waits for one of two event flags
Mailbox Demo
advocate_client.bas client program to send DCL requests to a server program (via a VMS mailbox)
(VMS mailboxes are similar to, but not identical to, a UNIX PIPE)
  advocate_server.bas server program to receive DCL requests from a client program (via a VMS mailbox)
  advocate_DCL_scripts "support" scripts to start the programs above
When you need
larger DCL symbols
multi-line_logicals_demo.bas Some apps like Apache save session data (like HTTP_COOKIE) as a DCL symbol. When the data is greater than 930 bytes, Apache will save the data as multi-line logical names. This program demos how you would do something similar from BASIC

  1. all operating systems support shell variables known as symbols
  2. VMS (and OpenVMS) also support a different data-passing method known as logical names
  3. programs wishing to create or modify logical names will need to call lib$set_logical or sys$crelnm
    Caveat: lib$spawn will allow you to make changes on copied data which is discarded upon exit of that spawned task
  4. While everyone knows how to create single line logical names from BASIC, multi-line logical names are a little more difficult
Password Stuff password_search.bas the name says it all
Peek peek_demo.bas Unlike most other BASIC implementations, VMS BASIC doesn't have a PEEK function but sometimes you need it to investigate further.
  peek_demo_test_run.bas see how variables are stored in an OpenVMS system
see how the Alpha compiler is able to achieve such high levels of performance relative to VAX
population_sim.bas a crude human population simulation to prove/disprove some things rolling around my head.
Sample output
sys$getjpi getjpi_demo.bas demos how to properly call sys$getjpi (get job process information)
sys$setddir show_default_demo.bas demos how a program can do the equivalent of the DCL command "$show default"
sys$getrmi getrmi_demo.bas demos how to properly call sys$getrmi (Resource Monitor Information)
  getrmi_demo_mscp.bas same as before except only returns mscp stuff (if mscp exists)
sys$qio qio-demo.bas yep, calling sys$qio from BASIC allows more control than PRINT and INPUT
Source Code Tools source_code_reporter.bas generate "code change" reports to justify your existence
  source_code_formatter.bas This horribly written hack has proved invaluable as a tool for locating coding problems introduced by other authors. Anyone who has inherited source code from another organization knows what I am typing about. Caveat: I've been meaning to rewrite this tool for a decade now but can never find the time. But this tool can format itself so maybe it's good enough for occasional use :-) 
Sequencer sequencer.bas When run from a DCL script, this program goes great lengths to ensure that your process, and only your process, gets the next number in a numerical sequence. I use this program so that an intercepted email account can temporarily access one of twenty subdirectories before I call MUNPACK to extract MIME attachments (if any) from cell phone messages. Of course, I need to run a different program to read the plain-text email if nothing was extracted :-)
terminal_characteristics_demo.bas the name says it all
Timer Demos timer-demo-easy.bas single (easy)
  timer-demo-hard.bas single (hard)
  two-timer-demo.bas two timers
  hiber-demo.bas demos how to pause program execution without using BASIC's SLEEP statement. Supports fractional seconds
VMS Mail vms_mail_send_demo.bas sending VMS MAIL programmatically without using DCL
  vms_mail_forward_demo.bas inspecting VMS MAIL forwarding
Watchdog watchdog.bas my own watchdog process (demos lots of systems calls)
Webification tool_webify_source_code.bas a tool to prepare source code for display in a web page (is webification a real word?)

OpenVMS BASIC standalone functions (file extension ".fun")

Some BASIC demos may require these standalone (most BASIC) functions:

Programs Notes compute Easter or Good Friday for any date after 1582. Necessary for writing an annual holiday generator. returns the current date-time in ccyymmddhhmmss format mime time function for smtp use returns the value of a desired DCL symbol returns the 64-bit data work found at the specified 32-bit address this function will attempt to save your data as a DCL symbol. If it can't (usually because the data is too large for your machine) then it will shift modes and save your data as multi-line logical names (emulates functionality found in the CGI interface of Apache for OpenVMS) submitting to batch from within BASIC translates a logical name
caveat: we used this function in the VAX days because it was much more efficient than calling lib$get_logical and easier to set up than sys$trnlnm. But there seems to be no performance hit when using lib$get_logical on Alpha so this  function is only included here incase I've included a few demos still calling it. undo so-called percent encoding (as well as some other stuff)

Question: So just what does the prefix WCSM stand for?
Answer: Waterloo Computer System Maintenance. That department morphed into something greater but the function prefix remains.

OpenVMS BASIC includes (file extension ".inc")

Some BASIC demos may require these standalone includes:

Programs Notes data structures required for item lists in system calls, etc. system declarations required to do system calls from BASIC
should not be used for new code development escape sequences required to embed VT terminal and LA printer inside your programs. (written for use on small VAX systems where it was not practical to control devices by system calls to the terminal driver) FMS (forms management system) definitions: functions and constants TCPware control block definitions

My BASIC Development Environment

If you want to compile my programs without modifying them, you should emulate my development environment. You do not need to use the directory name "dvlp" but subdirectory names are important. For example, many of my programs compiled in "dvlp" need to find standalone functions in sub-directory "[.fun]" or file record declarations in "[.fil]"

Directory File
[.dvlp] .bas
basic source code
DCL scripts for building some applications
[.dvlp.flb] .frm
FMS forms (created by dcl command: $fms yada.frm)
FMS form libraries
[.dvlp.fil] .rec
mapped string declarations (records) for relative and indexed files
open statements for relative and indexed files
file description language files for tuning rms files
[] .fun basic functions
[] .inc basic includes
[.dvlp.mar] .mar
macro-32 files
macro-64 files

BASIC Compiler bugs

Topic Programs Notes
modulus bug in
  1. I just (2012-08-01) discovered a bug in HP Alpha BASIC-1.7-000 (friends tell me it also exists on Itanium)
  2. Although you can divide large QUADWORD integers, the modulus function fails
  3. Here is a "C" version which works properly: basic_quad_mod_bug.c
  4. I just (2012-09-14) tested an experimental version of HP Alpha BASIC 1.7-001 which fixes this problem.
  5. Version Notes-1 Notes-2
    1.7-000 test fails at 2^32 bug
    1.7-001 test works up to 2^62 fixed
  6. CAVEAT: HP told me they will not be releasing this fix to the world so "if you have a support contract and want it fixed then you must input a support request"
modulus bug in
  1. I just (2012-09-01) discovered a bug in HP Alpha BASIC-1.7-000 (friends tell me it also exists on Itanium)
  2. Although you can divide large DECIMAL integers, the modulus function fails
  3. Here is a "C" version which works properly: basic_quad_mod_bug.c
  4. I just (2012-09-14) tested an experimental version of HP Alpha BASIC 1.7-001 which fixes this problem.
  5. Version Declaration Notes-1 Notes-2
    1.7-000 decimal(16,0) test fails at 2^32 bug
    1.7-001 decimal(16,0) test works up to 2^53 fixed
      decimal(17,0) test works up to 2^56 with compile warnings safer to use quad
      decimal(18,0) test works up to 2^59 with compile warnings safer to use quad
      decimal(19,0) test works up to 2^62 with compile warnings safer to use quad
  6. CAVEAT: HP told me they will not be releasing this fix to the world so "if you have a support contract and want it fixed then you must input a support request"

I just (2014.08.xx) found a bug in the current BASIC RTL (run-time library)

p.s. I was attempting to write code which would directly open SYSUAF which contains a key (err, index) based upon an UNSIGNED QUAD. Since VMS-BASIC has no unsigned data types an updated BASRTL would be of no use. Even still, I am surprised to learn that this bug was hanging around since 2005 when HP added the QUAD data type to the language (up until then you needed to use BASIC$QUADWORD defined in the STARLET library)

DECC / DEC-C/ OpenVMS-C / OpenVMS-C++


Caveats for developers:
  1. both C and C++ languages "appear" to be more complicated on OpenVMS than what you will see on UNIX, Linux or Windows so be sure to read OpenVMS specific documentation.
    1. C on OpenVMS ( )
    2. C++ on OpenVMS ( )
    3. HP-C Run-Time-Library Reference Manual For OpenVMS which is used by both languages ( )
      • tells you where your libraries are located
      • compares UNIX I/O to RMS I/O
      • introduces optional directives which will allow UNIX-dependent c programs to run on UNIX
        • eg. translate a file system spec from "//one/two/three.dat" to "[one.two]three.dat"
    4. One definition of Sensei (a  Black Belt  in Karate) is "one is has gone before". Many times you will attempt to solve a problem which has already been solved by someone else long before. Some of these solutions can be found here:
      1. which includes lots of C sources like:
      2. which includes lots of C sources like:
  2. When calling OpenVMS routines defined in the STARLET library, do yourself a favor and enable strict type-checking. This is done by inserting ...

    #define __NEW_STARLET 1

    ... before the library references you wish to be strict (for new programs it should be before all libraries). This way, your code will be in better shape to be ported to another OpenVMS hardware platform. In one of the programs below (sys_create_uid_101.c) I needed to add a few more lines (resorted to a union) to satisfy the compiler but the optimizer was able to generate a program which was byte-for-byte the same size as and earlier relaxed version.
  3. Some large projects (especially code originally written for UNIX/Linux) may require you to build with a so-called "make utility". MMK is the name of the OpenVMS utility used by many developers and can be downloaded here:
  4. Lots of open-source software works under GNV (Gnu Not VMS): while a related effort can be located here:

C Demo Programs

Programs Notes
Two cgi-demos (from 1995) for educational use only.
The second version is faster than the first.
chmod_demo.c changing VMS file protection bits
cmd_line.c reads command line arguments (and named logicals and/or DCL symbols)
descriptor_macro.c the $DESCRIPTOR MACRO is dumber than most people realize so use it with caution or NOT AT ALL
dec-device-control-codes.c see vt340-demo at the end of this table
diffie_hellman_demo.c Diffie-Hellman Key Exchange Demo (limited to 64-bit integer math)
dns_lookup_demo.c A very-cool LINUX socket programming to do Name Server lookups. It was not written by me but it works as-is on OpenVMS-8.4 Alpha with "TCPIP Services for OpenVMS v 5.7". It won't work from behind a firewall (without a few mods) but you'll get the basic idea.
Caveat: be sure to see RES_SEARCH_DEMO.c below which may be a bit more useful. Why? Library functions res_search() and res_query() work properly with IPv4 -and- I assume they also work properly with IPv6
do_100k.c This little test file came from OpenVMS Engineering (I kept it in homage to them) when we reported a 100k problem with CSWS 2.0 (Apache for OpenVMS). Drop this file into the scripts directory of your Apache server then trigger it from a browser like so:
It will help you test your Apache server as well as assist in confidence tests with your network admin people.
ebcdic-ascii-demo.c convert between EBCDIC and ASCII character sets
getuai.c demos use of getuai (get user authorization information)


generate a UID (with a tip of the hat to Jim Duff)
generate a GUID (with a tip of the hat to Stephen Hoffman)
Hello World

every site has one
introductory "hello world" program for OpenVMS
adds a few system calls to the previous program
HTTP connection test-tool from Hunter Goatley (Process Software)


LDAP stuff from DEC-Compaq-HP
MariaDB - MySQL
An alternate fork of MySQL (installation tips and security quirk)
demo-1: a "hello world" demo for mysql
demo-2: doing some real SQL work (to develop C->MySQL skills)
demo-3: unfinished direct data import tool (intermediate CSV is not required)
demo-4: data import tool (tab-delimited source file is required)
caveat: click here to see my production import tools.
DCL build script (c only)
DCL build script (c or c++)
my starting point for a conversion from RMS to MySQL (required for demo-4)
playing with SQL (creating tables, displaying execution plans, etc.)
caveat: click here to see my production import tools.
this program creates 3 pipes before calling vfork
this C program is executed by the vfork
this DCL script is optionally executed by the vfork
quad_mod_demo.c playing with quads (long long) in "C"
this program was used to verify some problems with HP Alpha BASIC 1.7-000
res_search_demo.c As of October-2014 I think this is the only reasonably complete OpenVMS demo on the internet showing how to use res_search() and res_query() then extracting A, MX and NS records. If anyone knows a better/easier way to to extract this information on OpenVMS (perhaps using library functions I don't know about) then please send me the details.
1) Many library functions are available for Linux (and I was tempted for a short while to begin porting a half dozen or so but why reinvent the wheel if others have gone before me? I certainly couldn't be the first OpenVMS application programmer standing before this chasm, right? Also, the responsibility of keeping the C/C++ libraries up-to-date squarely lays with HP
2) Anyone who has viewed the official ISC source code for nslookup.c or dig.c might be wondering WTF? I'm certain they are kept remark-poor to thwart modifications by non-specialists. Meanwhile, I am certain that professional spammers already know how to extract MX records.
rms_c_ug_example.c This program is an annotated version of RMSEXP.C found in chapter 2 of the HP C User's Guide. Any newbie wishing to use RMS from C or C++ should first look at this program before you write a single line of code
smtp-check.c SMTP connection test-tool from Hunter Goatley (Process Software)
sys_sndjbcw.c sndjbc - submitting a job to a batch queue (this will enable you to submit a job on behalf of another user for the express purpose of having that user send a file to another system via SFTP or SCP)
sff_demo_c.c demos function tcpip$send_from_file() which is a nifty way to send SMTP messages to your own stack without opening a connection to port #25
tcpip$tcp_client_qio.c my presentation of a client demo program found in vms folder sys$examples (copyright by HP)
1. this program uses sys$qiow rather than Berkeley sockets and is synchronous
2. a synchronous version (based on sys$qio) will be published soon
timezone_demo.c display the current time translated to any other time zone
unix_hater.c does the "C" example in the UNIX Hater's Handbook actually compile? (yes)
Old School VT Programming
(note: SMG$ is one of five OpenVMS RTLs)
display colored text on real VT terminals (or any good emulator) without SMG$
this file contains escape sequences used to control popular DEC peripheral devices
this limited demo employs SMG$ routines to display colored text on a virtual terminal
vms_lock_dlm.c Accessing the OpenVMS DLM (Distributed Lock Manager)

C++ Demo Programs

Programs Notes
hello_world.cpp every site has one
string_demo.cpp This string demo is very interesting. Why?
  1. at first glance these C++ strings appear much more BASIC-like than those found in traditional C. But this syntax seems closer to what you see in Java, JavaScript, or C#
  2. Many traditional third generation languages, like HP-BASIC for OpenVMS, limit string size to 32,767 bytes. I have tested this C++ demo up to a string size of 1,999,000 bytes (I could have gone higher but became bored) and found that it worked equally well with:
    1. "HP C++ V7.3-009 for OpenVMS Alpha V8.4" (complied and linked in 32-bit mode)
    2. "CodeBlocks 12.11 on Windows 7"

Apache Specific

Apache Module Authentication



files description
mod_auth_openvms this is HP's Apache plugin for authenticating against SYSUAF in OpenVMS
(published by Compaq)
  1. this module was published by Compaq before the merger with HP
  2. This 2015-02-28 production file hasn't changed since 2003-01-15 (I present it here for reference purposes)

Comments: with the benefit of 12 years of hindsight

  1. Parts appear to be derived from a Solaris program written before y2k (keep in mind that Solaris usernames are case sensitive)
  2. as written, this plugin is very inefficient. It contains two hooks:
    • hook-1 will fire for every transaction "requiring Apache authentication" in the whole system whether this plugin is enabled in that directory or not. This means the hook is always fired but has been defaulted to DECLINE. When enabled, will access SYSUAF
    • hook-2 will fire for every transaction "requiring an Apache authorization" in the whole system whether this plugin is enabled in that directory or not. This means the hook is always fired but has been defaulted to DECLINE. When enabled, will search for the current USERNAME in an external GROUP FILE.
  3. IMHO it might have been a better idea for Compaq to operate both routines under a single hook which would make the plugin slightly less parasitic. Alternatively, they could have published two plugin modules: "authentication only" and "authentication and authorization"
  4. Another problem with the code under hook-2 is that the username test is case-sensitive. OpenVMS usernames are up-cased before going through SYSUAF authentication. This means that the GROUP FILE associated with hook-2 needs to contain both upper and lower versions of every username but someone logging in with a mixed-case username will still be bounced.  
  5. the first two "c language" tests near the top of hook-1 are in the wrong order. This plugin could be made a tiny bit less parasitic if the very first line of code was the test of fUserEnable rather than a call to ap_get_basic_auth_pw (why test for a password in places where the module is disabled?). my DCL script to build mod_auth_openvms.c from HP's CSWS sources
mod_auth_vms_ext this is my alternative to mod_auth_openvms
  • this program in now fully functional (here is the flowchart)
  • it works with cookies, and/or username+passwords
  • it can (optionally) engage an indexed RMS-based "session cache" so the external authenticator is called less often (I do not think it would be too difficult to change this to a "global section" -- also called a shared memory object)
  • it spawns an external authenticator (can connect to any kind of database: ISAM or relational)
  • it can command a browser to raise the username-password dialog
  • it can command the browser to store a COOKIE (cookie data must be provided by your authenticator)
  • it can (optionally) do GROUP access restriction tests (group data must be provided by your authenticator) DCL build script
mod_auth_vms_rms will directly open an indexed RMS file to perform application-level authentication
mod_auth_vms_rms.c essentially identical to mod_auth_vms_ext.c (above) except that lib$spawn was replaced by directly accessing an RMS-file
(caveat: this program works but is not yet complete (need to finish the cookie logic)) DCL build script
Flowchart for Apache plugin: mod_auth_vms_ext
Block-0	detect:	desired cookie (might not exist)
		username+password (might not exit)
Block-1	optional cookie test enabled?		N	goto block 3 (check for username+password)
	desired cookie present?			N	goto block 3 (check for username+password)
Block-2	optional "session cache" enabled?	N	goto block 3 (check for username+password)
	cookie found in "session cache"?	Y	goto block 5 (user is known to this system)
Block-3	username+password present?		N	goto block 8 (put up a username+password dialog)
Block-4	call lib$spawn to run the external authenticator
	1) pass everything known so far: cookie, username, password
	2) cookie is tested first (it may not exist)
	3) username+password tests are performed only if the cookie test fails.
	4) the authenticator will return with pass/fail
	5) on a pass, the authenticator may also:
	   a) pass back a cookie to be sent to the browser
	   b) return group-information (only important if group tests are enabled) 
	did authenticator tests pass?		N	goto block 8 (put up a username+password dialog)
	do we need to write a cookie?		N	goto block 5 (user known to this system)
	instruct Apache to write-back a cookie
Block-5	at this point the user is known to this system, ...
	...but does he have access to the current area?
	optional "group access test" enabled?	N	goto block 7 (allowed)
	is this user's group in the group-list	N	goto block 9 (forbidden)
Block-7	exit plugin with OK (Apache continues processing this transaction)
Block-8	throw http response 401 ("unauthenticated") then
	forces browser to say raise a username+password dialog
	exit plugin
Block-9	throw http response 403 ("forbidden")
	exit plugin

gSOAP Specific (c)

When you check out the sample programs delivered with the gSOAP stack they seem fairly straight forward (right now I'm thinking about "calc") but most were created using the WSDL-last method. When someone hands you a WSDL then says "build client and server apps which will be part of a two way messaging system" things get complicated fast. You will be forced to use the WSDL-first method, and the tool wsdl2h (read as: wsdl-to-h) will stuff your SOAP variables deep inside complicated structures and unions then pass the whole mess to you with a pointer. If the WSDL contains more than 100 fields like the one I saw a few months ago, you might want to tackle a smaller project first just to develop skills.

Last year I used the WSDL-last method to create a Java-based web service under Tomcat/AXIS2 called "SimpleService". This service only had three methods: ssADD, ssSubtract, and ssEcho (I added the "ss" prefix to my variables so I would see them in various places in the code). Then I used AXIS2 to generate a WSDL which would be used to build this gSOAP service with the same functionality.

gSOAP demo web service

this WSDL was generated by AXIS2 (using:
this is a simple gSOAP client (add, subtract, echo)
this is a simple gSOAP service (add, subtract, echo)
this is a simple gSOAP service with a few more bells and whistles
the service requires this wrapper if you want to access it from Apache
common build script (DCL)
service build script (DCL)
client build script (DCL)
gSOAP demos (other)

this gSOAP sample client has been tweaked to support OpenSSL (demonstrates three different SSL client contexts)
doesn't do anything useful other than traversing a DOM-loaded SOAP packet (needs more work; would like to produce a better version in C++)
gSOAP reference
plugin code to allow Apache access to gSOAP (problems highlighted in yellow)
note: do not use this with OpenVMS (Brett Cameron has rewritten this plugin for his gSOAP distro)

gSOAP Specific (c++)

Brett Cameron and John Apps (two overworked HP employees) have provided a really good set of gSOAP sample programs written in HP-C but nothing (as of 2012) written in HP- C++. So here are my unofficial offerings of sample programs tweaked for use with HP-C++ for OpenVMS.

  1. Large gSOAP programs written in C++ seem clearer than the same ones written in C. Consider using C++ if you you want your gSOAP code to me more easily maintainable by other programmers.
  2. When the gSOAP preprocessor "soapcpp2" generates C++ code it will use a ".CPP" extension
  3. HP-C++ defaults to a file extension of ".CXX" while competing compilers default to ".CPP" so be sure to include a fully qualified file name.
gSOAP Calc Samples

gSOAP sample Client program from //gsoap/samples/calc++/calcClient.cpp
gSOAP sample Server program from //gsoap/samples/calc++/calcServer.cpp
DCL script to build these two gSOAP sample programs on OpenVMS
gSOAP sample Client program (w/OpenSSL) from //gsoap/samples/calc++/calcClient.cpp
(this last  demo has only been tested on Windows-7)

Porting OpenSSL to OpenVMS

While it is possible to build OpenSSL from public sources, the libraries will be okay but at least one of the demonstration applications will not work without modifications. The main reason for this involves use of the UNIX I/O select() statement to test for I/O readiness. While this is perfectly acceptable in the UNIX/Linux world, select() can only be used to wait for network I/O in the VMS and Windows worlds. There are two possible fixes for this:

  1. use a different technique to detect the start of keyboard I/O
  2. use a VMS-recommended technique to use a socket to connect to SYS$COMMANDND
Programs Notes
s_client.c This program was found in kit CPQ-OpenSSL-1.0A (OpenSSL 0.9.6b) published July 2001 by Compaq
It shows how to create a socket (TerminalSocket) to communicate with stdin (your keyboard)
No Compaq/HP copyright was included with this package.
While this program is copyrighted by Eric Young, the VMS changes are not copyrighted by anyone.
"I think" it was modified by someone at Compaq Computer Corporation
term_sock.c This program was found in kit CPQ-OpenSSL-1.0A and is used to create a socket (TerminalSocket) to communicate with stdin (your keyboard).
No Compaq/HP copyright was included with this package or this file.
"I think" it was written by someone at Compaq Computer Corporation.
It allows the programmer to get around the "bad select 38" problem
term_sock.h This c header supports term_sock.c
No Compaq/HP copyright was included with this package or this file.
"I think" it was written by someone at Compaq Computer Corporation
select_demo.c A demo program (derived from HP's UNIX to OpenVMS porting guide) to show how to use select() 

Webpage Hit Counters

We have always been told to never use hit-counters because they consume precious resources. But many rinky-dink sites, especially some on corporate intranets sitting behind a firewall, need them for good P.R. with other departments.

Image-based Counters

These seem to be the gold-standard in counters. Between 1995 and 2000 (when web servers were powerful platforms serving up mostly static webpages to underpowered desktop PCs sporting Pentium-2 or Pentium-3 processors) most sites used a bit of freeware written by Muhammad Muquit named "count". Needless to say I am envious of his programming skills. But this solution places a more-than-trivial computational burden on the server. Why? Updating a counter file is the easy part. Using the digits to reference a graphics library of individual digits then assemble the binary pieces scan-line by scan-line into a resultant GIF is the hard part.

Text-based Counters

I'm running an overworked decade-old server (AlphaServer DS20e installed in 2002) and I think the time has come to shift the computational burden from the server to the client. I have a little "C" program ready which increments the counter file then sends back the plain-text result. The calling webpage uses a small amount of AJAX (~20 lines) to accomplish the task then the browser is responsible for displaying the count. The browser may not have access to all the cool image sets seen in Muhammad's offering but that may not be as big a deal as you might think. I will publish it soon.


Web Page Hit Counter (2.4 + 2.6)

Technical Observations (2013-11-xx)
Updated DCL script for use with CSWS (aka Apache on OpenVMS)

$ on error then $ continue
$ t = f$cvtime(,,"TIME") -":"-":"-"."
$ p = f$getjpi("","pid")
$ f = f$trnlnm("csws_server_root") + "count_" + p +"_" + t +".gif"
$ set prot=(S:rwed,o:rwed,g:rwed,W:rwed)/default
$ define/user/nolog sys$output 'f'
$ mcr www_root:[scripts]count.exe
$ m=1 ! DCL
$ if (m.eq.0)
$ then ! MIME from a file
$	APACHE$DCL_BIN 'f';1 ! MIME header
$ else ! MIME from DCL
$!	write sys$output f$fao("!AS!/!/","Content-type: image/gif")
$	write sys$output f$fao("!AS!/!AS!/!/","Content-type: image/gif","Cache-Control: no-cache, no-store")
$ endif 
$ APACHE$DCL_BIN 'f';2 ! GIF data
$ del/nolog 'f';*
$ exit

Hybrid Programming

OpenVMS DCL scripts

Category DCL Scripts Notes
DECnet communication client (start a remote server then send it some messages) server (echo messages back to client)
Intercepting an
FTP/SFTP login
Example DCL script for properly setting up FTP/SFTP
DCL script to intercept an FTP/SFTP login then submit a login helper job
DCL script which will wait for the network partner to exit then process received file(s)
(similar to what happens at the end of an XCOM transaction)
More notes can be found here: OpenVMS Notes: TCPware
FTP Scripts a script which can FTP from three different stacks: MultNet, TCPware, and TCPIP Services
uppercase - lowercase
switcheroo a tool to easily toggle your account between two modes: case-sensitive and normal a tool to easily down-case filenames. Intended for SSH key files.
Apache Support a little batch job to rotate apache client log files every 24 hours
also will (optionally) do monthly maintenance of apache process logs
Monitoring (AXP only)
original script
tweaked for calling from your LOGIN.COM

OpenVMS Macro32 source code

Programs Notes
peek_byte_vax.mar Code to peek at bytes
peek_byte_function.mar Code to peek at bytes (function)
peek_any_int_vax.mar Code to peek at bytes, words, and longs

OpenVMS Programming

Introduction to OpenVMS programming

It was a lot tougher before y2k

It was a lot tougher learning how to write VMS applications in the 1980s. Why? DEC charged big-bucks for everything including hardware, software, training and documentation (including pocket programming cards!) Many IT people wondered if that was why DEC used a dollar sign ($) for the VMS/DCL command-line prompt.

First off, you needed the 32-binder  Orange Wall of VMS documentation  which I remember being around $5k for the initial purchase. Then, even if you already knew how to program in one of the many DEC-supported programming languages, you still needed to attend DEC language-specific courses to learn how to do system calls. This meant you needed to work for a company with deep pockets, or needed to get VMS-specific training in college or university.

In the early 1990s, DEC renamed the product line from VMS to OpenVMS at the same time they introduced the 64-bit Alpha hardware line as a successor to 32-bit VAX. During this time the  Orange Wall  became the  Gray Wall  

Then Things Changed

In 1998, DEC was purchased by "PC manufacturer" Compaq.

In 2002, HP purchased (err, merged with) Compaq. HP restored some in-house training but now OpenVMS was just one of many software offerings from HP's, and I think OpenVMS has been lost in the mix.

Although my employer did provide us with the 32-binder Gray Wall, we had to learn how to interface VMS BASIC to VMS the good old-fashioned hard way: by hacking. In 1993 I fortunately stumbled across a copy of Writing VAX/VMS Applications Using Pascal (Author: Theo De Klerk, Published: 1991 by Digital Press) in DEC's student retail store in Bedford, Massachusetts. I had learned Apple Pascal in late 1970s so found it relativity easy to convert many of these programs into DEC-BASIC and DEC-C. This book contained many descriptions of VMS subsystems and was full of "system calls" on how to access them. These books pop up every so often on and I think every serious OpenVMS programmer should own a copy.

Okay so that was then and this is now. To the best of my knowledge, you can only get the OpenVMS Documentation CD-ROM by purchasing it from HP, buying a used copy on eBay, or begging a friend to make you a copy. But if you use HP's online documentation along with examples from this book, you will learn how to become a VMS BASIC developer much faster than me.

Online HP Manuals + Documents

Advanced hacking (system services)

Many novice programmers do not know about this cool feature to trace system calls originating from your process (DCL or otherwise). So if you have the necessary privs, then try this experiment:
  <sr> = system response <ur> = user response -------------------------------------------------------- <sr> $
<ur> set process /sslog=(state=on,count=4) ! enable tracing on YOUR process
<sr> $
<ur> monitor disks <sr> screen fills with disk i/o statistics <ur> now wait for 4 or 5 seconds then hit <ctrl-c> <sr> MONITOR> <ur> exit <sr> $ <ur> set process /sslog=(state=off) ! disable tracing <sr> $ <ur> set process /sslog=(state=unload) ! this closes the file <sr> $ <ur> ANALYZE/SSLOG/FULL/WIDE/OUTPUT=ss_trace.txt ! human readable data goes to this file <sr> $

Official Documents:

Noteworthy C/C++ demos at other sites

Noteworthy C/C++ articles and manuals

Back to OpenVMS
Back to Home
Neil Rieck
Kitchener - Waterloo - Cambridge, Ontario, Canada.