🚨 Oracle not porting Rdb to x86 and EOL on Itanium 12/2027 🚨

The ACMS Runtime, Rebuilt for Modern Systems

Full-fidelity DEC OpenVMS ACMS for Linux and macOS: task definitions, server processes, terminal I/O, and a rich step library β€” migrated applications run without retraining.
adu β€” banking application
! Step 1 β€” compile the CDD record repository
$ vxcdd --add banking.cdo
ok ACCOUNT_WKSP, TRANSFER_WKSP, AUDIT_WKSP (layout_hash e3f9a1)
 
! Step 2 β€” compile server group (GDF)
$ adu_compile banking_servers.gdf --cdd banking.cdd.db
ok server group BANKING_SERVERS β†’ banking_servers.cpp
ok linked β†’ banking_servers.so
 
! Step 3 β€” compile task definitions (TDF)
$ adu_compile funds_transfer.tdf --gdf banking_servers.gdf --compile
parsing TDF… 3 tasks
resolving workspaces… ok (layout_hash e3f9a1 βœ“)
generating C++… funds_transfer_task.cpp
compiling… funds_transfer.so
 
! Step 4 β€” install into acmsd
$ acmsctl install application BANKING
BANKING installed β€” 3 tasks, 2 server groups
ACMS_NORMAL
 
$ acmsctl call BANKING FUNDS_TRANSFER
ACMS$_NORMAL β€” task completed.
ADU parser βœ“ live
ACMS$ services 12 impl.
workspace ABI βœ“ live
The problem

ACMS shouldn't be the reason you stay on OpenVMS.

For thirty years, ACMS has been the transaction-processing backbone of business-critical OpenVMS applications. Migrating off OpenVMS has always meant rewriting the ACMS layer from scratch β€” re-implementing task orchestration, workspace passing, server lifecycle, and the forms-driven user interface in something entirely different. Months of work, indefinite risk.

The old answer

Hand-port every TDF into a custom service. Rewrite COBOL step procedures as web handlers. Re-think workspace semantics. Bind to a new persistence layer. Re-test under load. Retrain operators.

Typical timeline: 12–36 months per application. Typical failure mode: the new code never matches the old behaviour.

The VX/ACMS answer

A native Linux runtime that is ACMS as far as your source code can tell. The same TDFs compile. The same server procedures load. The same workspace passes by reference. The same ACMS$ services resolve.

Effort shifts from port to recompile.

Source compatibility

Three boundaries. Unchanged for your code.

Your migrated VMS applications meet VX/ACMS at three contracts. Each one is specified in the VSI ACMS manuals; each one is honoured by VX/ACMS on Linux exactly as your source expects.

TDL β€” Task Definition Language

Your .TDF, .GDF, and .ADF files compile through the ADU unchanged. Task structure, workspace declarations, EXCHANGE / PROCESSING / ATOMIC steps, exception handlers β€” all of it.

ACMS$ Services β€” System Interface

ACMS$CALL, ACMS$SIGN_IN, ACMS$START_CALL, ACMS$RAISE_STEP_EXCEPTION β€” the services your code links against. Same signatures, same status codes, same semantics.

FORMS$ β€” DECforms Callable API

VX/ACMS binds to VSI's DECforms runtime (also available on Linux). EXCHANGE steps marshal workspace records into FORMS$ records and pump events through FORMS$TRANSCEIVE exactly as on VMS.

What you haveVX/ACMS support
Task Definition Files (.TDF)Compiles unchanged β€” including DCL prelude, SET DEFAULT, workspace WITH ACCESS, TASK ARGUMENTS, IF / WHILE / REPEAT / GOTO / ATOMIC.
Group Definition Files (.GDF)Compiles unchanged β€” SERVER blocks, PROCEDURE SERVER IMAGE, INITIALIZATION / TERMINATION / CANCEL PROCEDURE, dictionary-qualified workspace refs.
Application Definition Files (.ADF)Compiles unchanged.
Menu Definition Files (.MDF)Coming v1 β€” menu rendering arrives with the CP integration.
CDD record definitionsAuthoritative source via the CDD$ callable API; layouts feed both ADU and the COBOL compiler.
COBOL step proceduresVMS-shape signature preserved β€” PROCEDURE DIVISION USING, workspaces by reference, status via RETURN-CODE.
C / C++ step proceduresNative β€” same signature unsigned int NAME(WKSP *a, WKSP *b); status via return value.
System workspaces (ACMS$SELECTION_STRING, etc.)Implemented.
DECforms (FORMS$ API)CP integration in flight β€” links VSI's Linux libvxdf*.
Queued tasks (QTI)v1 β€” surface + drain.
Distributed transactions (DDTM)v1 β€” SQLite-backed single-resource bracket; DDTM shape preserved for v2.
ACMSDI / TPware (Windows desktop)v2 β€” deferred per scope.
Distributed multi-node clusteringv2 β€” single-server is the v1 scope.
TDMS formsOut of scope β€” migrate to DECforms.
Runtime architecture

Faithful to ACMS. Native on Linux.

Every ACMS component you know is here. Where VMS used P0 mappings and global sections, we use POSIX shared memory. Where VMS used DECnet, we use UNIX-domain sockets. The shapes match the VMS manuals; the substrate is modern Linux.

acmsd
VMS: ACC
Root daemon. Manages the SQLite control DB, spawns child processes, owns the operator socket.
acms-exc
VMS: EXC
Per-application task interpreter. Drives IF / WHILE / REPEAT / ATOMIC / EXCHANGE / PROCESSING steps against dlopen'd task .so files.
acms-sp
VMS: SP
Procedure server pool. Loads server group .so files via dlopen; dispatches step calls from EXC.
acms-cp
VMS: CP
Per-submitter FORMS$ / menu process. Bridges terminal I/O through DECforms libvxdf* on Linux.
acms-qti
VMS: QTI
Queued task initiator. Drains the SQLite-backed task queue; submits deferred tasks to EXC.
acms-atl
VMS: ATL
Audit trail logger. Writes structured audit events from all components via the SWL log library.
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ acmsd (ACC) β”‚ β”‚ SQLite: control.db Β· audit.db Β· queue.db β”‚ β”‚ operator socket Β· child lifecycle β”‚ β””β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β” β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β” β”Œβ”€β–Όβ”€β”€β” β”Œβ”€β–Όβ”€β”€β” β”‚ acms-excβ”‚ β”‚ acms-sp β”‚ β”‚ cp β”‚ β”‚ qtiβ”‚ β”‚ (EXC) β”‚ β”‚ (SP) β”‚ β”‚(CP)β”‚ β”‚ β”‚ β”‚ task │◄─► dlopen β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ interp β”‚ β”‚ servers β”‚ β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”˜ β”‚ POSIX shm_open / mmap (workspaces) β”‚ UNIX-domain sockets (CBOR frames) β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β” β”‚ libacms β”‚ ← ACMS$CALL / ACMS$SIGN_IN / … β”‚ _si.so β”‚ agent callable surface β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
9
runtime components
12
ACMS$ services implemented
0
bytecode interpreters
C++20
implementation language
Zero-copy workspace passing. Workspaces are POSIX shared memory segments mapped at the same layout hash in every process. EXCHANGE steps move data without copying β€” the EXC and SP processes read and write the same physical pages. Only TASK ARGUMENTS copy boundaries cross the submitter-EXC split.
Inside the ADU

Your TDFs become native C++.

The Application Definition Utility parses your TDF, GDF, ADF, and MDF sources, resolves workspace records through the published CDD$ callable API, and emits clean C++ β€” one construct per TDL construct. The C++ is compiled and linked into a deployable .so per task and per server. No bytecode interpreter sits between your source and the CPU.

TDF source in

! funds_transfer.tdf
REPLACE TASK FUNDS_TRANSFER
    WORKSPACES ARE
        ACCOUNT_WKSP,
        TRANSFER_WKSP,
        AUDIT_WKSP;

    TASK ARGUMENTS ARE
        ACCOUNT_WKSP WITH ACCESS MODIFY,
        AUDIT_WKSP   WITH ACCESS WRITE;

    BLOCK
        EXCEPTION HANDLER
            MOVE "FAILED" TO AUDIT_WKSP.MSG;
            PROCESSING CALL LOG_AUDIT
                USING AUDIT_WKSP;
            EXIT TASK;

        PROCESSING CALL READ_ACCOUNT
            USING ACCOUNT_WKSP;

        IF ACCOUNT_WKSP.BALANCE
                < TRANSFER_WKSP.AMOUNT THEN
            MOVE "NSF" TO AUDIT_WKSP.MSG;
            EXIT TASK;
        END IF;

        PROCESSING CALL DEBIT_ACCOUNT
            USING ACCOUNT_WKSP, TRANSFER_WKSP;
    END BLOCK;
END DEFINITION;

Native C++ .so out

/* Generated by adu_compile */
extern "C" acms_status_t
task_FUNDS_TRANSFER_run(exc_ctx_t *e,
                        acms_runtime *rt,
                        exc_workspace_t *ws,
                        uint32_t n_ws)
{
  try {
    try {
      {
        const char *args[] = {"ACCOUNT_WKSP"};
        auto rc = acms_rt_dispatch(e, rt,
            "READ_ACCOUNT", ws, n_ws, args, 1);
        if (rc != ACMS_NORMAL)
          throw acms_rt_exception{rc};
      }
      if (acms_rt_field_i32(ws, n_ws,
              "ACCOUNT_WKSP", "BALANCE")
          < acms_rt_field_i32(ws, n_ws,
              "TRANSFER_WKSP", "AMOUNT")) {
        acms_rt_move_str(ws, n_ws,
            "AUDIT_WKSP", "MSG", "NSF");
        return ACMS_NORMAL; /* EXIT TASK */
      }
      /* DEBIT_ACCOUNT … */
    } catch (acms_rt_exception &) {
      /* EXCEPTION HANDLER */
      acms_rt_move_str(ws, n_ws,
          "AUDIT_WKSP", "MSG", "FAILED");
      return ACMS_NORMAL;
    }
  } catch (acms_rt_exception &x) {
    return x.status;
  }
  return ACMS_NORMAL;
}
Reviewable, debuggable output. Generated C++ is one construct per TDL construct β€” no opaque interpreter, no hidden state. git diff tells you exactly what an ADU version bump changed. Debuggers and profilers see function names that match your TDF identifiers.
Implementation status

What's live. What's coming.

VX/ACMS v1 targets the full single-server deployment model used by the overwhelming majority of production ACMS estates. Verified against large customer applications including multi-million-line COBOL codebases.

ADU Compiler live

Full TDF / GDF / ADF parser and C++ emitter. MDF support arriving with CP. CDD integration via vxcdd and the published CDD$ callable API.

  • TDF: all task constructs (BLOCK, IF, WHILE, REPEAT, GOTO, ATOMIC, MOVE, GET MESSAGE)
  • GDF: SERVER blocks, procedure server image, init/term/cancel procs
  • ADF: application definitions

Runtime Core live

EXC task interpreter, SP procedure server, workspace shared memory, IPC (CBOR over UNIX-domain sockets), ATOMIC SQLite bracket, EXCHANGE step machinery.

  • acmsd / EXC / SP / ATL / SWL
  • POSIX shm workspaces (zero-copy)
  • 12 ACMS$ services implemented

FORMS$ / CP v1 soon

Per-submitter CP process with DECforms integration via VSI's Linux libvxdf*. Completes the EXCHANGE step pathway for terminal-I/O-driven applications.

  • Menu rendering (MDF)
  • FORMS$TRANSCEIVE / FORMS$RECEIVE
  • DECforms record marshalling

QTI / Queued Tasks v1 soon

SQLite-backed task queue with QTI drain process. Queued task surface API live; drain-to-EXC dispatch arriving in the next release.

Clustering / DDTM v2

Multi-node ACMS and true distributed transaction management (DDTM/XA) are scoped for v2. The v1 ATOMIC bracket preserves the DDTM interface shape so application code needs no changes at upgrade.

ACMSDI Gateway v2

The Windows desktop TPware interface (ACMSDI) and the HTTP/JSON management API are v2 scope items. Contact us if these are blockers for your migration timeline.

Frequently Asked Questions

Curious about how Sector7 can facilitate your application migration? Explore our FAQs for expert insights.

What is VX/EDT and when would I use it?

VX/EDT is Sector7’s faithful reimplementation of the DEC OpenVMS EDT editor for Linux and macOS. It preserves familiar line-mode commands, ncurses screen mode, GOLD-key keypad behaviour, and common qualifiers so teams moving off OpenVMS can keep the same editing workflow on POSIX systems.

For the broader platform pictureβ€”languages, runtimes, and production cutoverβ€”see Sector7’s overview of OpenVMS to Linux and UNIX migration and the technical tools directory.

Do OpenVMS EDT line-mode commands work the same way in VX/EDT?

Yes. VX/EDT is built around a drop-in compatible command set: navigation, FIND / FNDNXT, SUBSTITUTE with qualifiers such as /GLOBAL and /QUERY, buffer operations, INCLUDE / WRITE, and the usual range syntax (THRU, WHOLE, REST, and so on). Commands remain case-insensitive, matching OpenVMS EDT expectations.

Enter full-screen editing with CHANGE or C; return to the asterisk prompt with Ctrl/Z. The on-page command reference summarises behaviour for quick lookup.

How does the GOLD key work on a PC or Mac keyboard?

On OpenVMS terminals, GOLD is typically F1 / PF1. VX/EDT follows the same model: press GOLD, then the second key (for example GOLD+F2 for BOTTOM, or GOLD plus keypad keys in screen mode).

On laptops without a dedicated function row, use Fn with F1 as needed. The Screen Mode section on this page lists PF keys, cursor GOLD combinations, Ctrl keys, and GOLD+keypad bindings for day-to-day reference.

Where does VX/EDT read EDT.INI from?

At startup VX/EDT checks, in order: the path in the $EDT_INI environment variable (if set), then $HOME/EDT.INI, then $HOME/edt.ini. Lines beginning with !, #, or ; are treated as commentsβ€”in both EDT.INI and -command script files.

Use DEFINE KEY and DEFINE MACRO entries to persist PF-key, GOLD, and Ctrl bindings across sessions. The Startup & Configuration section documents invocation flags and a sample EDT.INI.

Can VX/EDT run from a command file or non-interactive workflow?

Yes. Launch with edit <file> -command <script> (or the -command=<script> form) to execute a sequence of EDT commandsβ€”useful for scripted edits, repeatable migration steps, or CI-style checks alongside other tooling.

For larger automation and assessment across a codebase, many teams pair editor workflows with LegacyScan and Sector7’s broader toolset bundles.

How do undo and redo work in VX/EDT?

UNDO (U) restores the editor to the state before the last text-changing command, with up to 100 levels of history. Each undo pushes the current state onto a redo stack so REDO can re-apply the last undone change.

Captured state includes buffer contents, named buffers, cursor position, direction, selection anchor, active search string, and delete buffersβ€”mirroring the depth teams expect from OpenVMS EDT-style editing.

What is required to build VX/EDT from source?

VX/EDT ships as a single-file C++17 source module linked against ncurses (available by default on macOS and typical Linux distributions). A POSIX toolchainβ€”clang++ or g++β€”is sufficient; there are no additional runtime dependencies beyond the OS curses library.

The optional PRINT command expects a working lpr or lp line-printer interface when used. Exact compiler examples appear in the Building VX/EDT section on this page.

Where can I get help with a larger OpenVMS migration beyond the editor?

VX/EDT removes a common friction pointβ€”keeping the EDT editing experience on modern platformsβ€”but most production moves also involve languages, system services, databases, and operational cutover. Sector7 has delivered large-scale OpenVMS migrations since the 1980s using proprietary converters and proven methodology.

Explore migration services (including the assessment process and zero code freeze approach), browse the VX/TOOLS technical catalog, and contact us to discuss scope, timelines, and tooling fit.

Transform Your Legacy Software Today!

Get In Touch
Unlock the potential of your legacy software with our expert migration services.