VX/JSP - OpenVMS Print & Batch
Overview
VX/JSP is a source-compatible reimplementation of the OpenVMS job controller and print/batch queue manager for Linux. It reproduces the VMS spooling subsystem as a set of cooperating processes plus a linked runtime library, and it implements the two system services applications already call, SYS$SNDJBC for request submission and queue control and SYS$GETQUI for queue information queries, with the same function and item codes as on OpenVMS.
VX/JSP ships as an add-on to VX/DCL: the familiar verbs SUBMIT, PRINT, INITIALIZE/QUEUE, START/QUEUE, SET QUEUE and SHOW QUEUE are parsed by VX/DCL and lowered onto the VX/JSP services. Batch scripts, print jobs, forms and queue definitions migrate without changes, so organizations keep identical batch and print behaviour on Linux without rewriting code or retraining operators.
<div class="s7-tech-embed" data-vxjspd-body-embed="1" data-technical-mega-embed="1" lang="en"><h2 id="architecture">Architecture and components</h2><p>
VX/JSP is not a single binary. It is a multi-process spooling subsystem: a job-controller
daemon, one queue-manager process per active queue, and a symbiont process per running job,
plus a linked static library that exposes the OpenVMS queue, job and form on-disk formats
through a C API and the <code>SYS$SNDJBC</code> and <code>SYS$GETQUI</code> system services.
It runs as an add-on to VX/DCL: DCL verbs such as <code>SUBMIT</code>, <code>PRINT</code>,
<code>INITIALIZE/QUEUE</code>, <code>START/QUEUE</code> and <code>SHOW QUEUE</code> are parsed
by VX/DCL and lowered onto the VX/JSP API and services. The table maps each OpenVMS component
to its VX/JSP process.
</p><div class="table-wrapper"><table><thead><tr><th>OpenVMS equivalent</th><th>VX/JSP process</th><th>Role</th><th>Status</th></tr></thead><tbody><tr><td><code>JOB_CONTROL</code> (JBC)</td><td><code>jspctl</code></td><td>Job-controller daemon. Owns the master and queue-list files, spawns and reaps queue managers, and dispatches control requests.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>QUEUE_MANAGER</code> (per queue)</td><td><code>qmgr</code></td><td>One process per active queue. Schedules pending jobs, enforces the job limit, and starts symbionts.</td><td><span class="ac-live">live</span></td></tr><tr><td>Print/batch symbiont (<code>PRTSMB</code>)</td><td><code>pjob</code></td><td>Per-job worker. Prints a file to a device, or executes a DCL command file for a batch job.</td><td><span class="ac-live">live</span></td></tr><tr><td><code>SHOW QUEUE</code> monitor</td><td><code>qmon</code></td><td>Queue, job and symbiont monitor. Text mode plus an optional X11/Qt GUI.</td><td><span class="ac-live">live text</span> <span class="ac-v1">GUI optional</span></td></tr><tr><td>Repair tool</td><td><code>qfix</code></td><td>Interactive repair of damaged queue and job records.</td><td><span class="ac-live">live</span></td></tr><tr><td>Status probe</td><td><code>jspmgr</code></td><td>One-shot check that prints controller running or stopped state and the spool directory.</td><td><span class="ac-live">live</span></td></tr><tr><td>Networked printing (LATSYM / TCP)</td><td><code>libxrxsym</code>, <code>telnetsym</code></td><td>Loadable Xerox device symbiont and a TCP terminal-server symbiont for printing over the network.</td><td><span class="ac-live">live</span> <span class="ac-v1">telnetsym built on demand</span></td></tr></tbody></table></div><div class="callout"><strong>Privilege model.</strong> The controller must change uid and gid to run each job as
its submitting user. On Linux this is handled either by installing the controller setuid
root, or by granting the <code>cap_setuid</code> and <code>cap_setgid</code> capabilities to
the queue manager and symbiont, rather than through the VMS privilege model.
</div><h6>Request flow</h6><p>
A DCL command enters through VX/DCL, which calls <code>SYS$SNDJBC</code>. The service builds a
job stream and writes it into the jobs file, then signals the controller through a shared
request record. The controller routes the request to the right queue slot and feeds the
queue's <code>qmgr</code> over a FIFO; the queue worker then starts a <code>pjob</code>
symbiont to run the job.
</p><style>
.s7-tech-embed .process-flow {
margin: 1.5rem 0;
padding: 16px;
border: 1px solid var(--s7t-border);
border-radius: 10px;
background: rgba(255, 255, 255, 0.01);
}
.s7-tech-embed .process-stages,
.s7-tech-embed .process-branches {
display: grid;
gap: 10px;
}
.s7-tech-embed .process-stages {
grid-template-columns: repeat(5, minmax(0, 1fr));
}
.s7-tech-embed .process-branches {
grid-template-columns: repeat(2, minmax(0, 1fr));
margin-top: 10px;
}
.s7-tech-embed .process-stage {
min-width: 0;
padding: 15px;
border-top: 3px solid var(--s7t-accent);
border-radius: 6px;
background: var(--s7t-surface2);
color: var(--s7t-text);
}
.s7-tech-embed .process-branch {
border: 1px solid var(--s7t-note-bd);
border-top-width: 3px;
background: var(--s7t-note-bg);
}
.s7-tech-embed .process-number,
.s7-tech-embed .process-label {
display: block;
margin-bottom: 10px;
font-family: var(--s7t-mono);
color: var(--s7t-accent);
font-size: 0.76em;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
}
.s7-tech-embed .process-stage strong,
.s7-tech-embed .process-stage span:last-child {
display: block;
}
.s7-tech-embed .process-stage strong {
margin-bottom: 4px;
color: var(--s7t-text);
}
.s7-tech-embed .process-stage span:last-child {
color: var(--s7t-muted);
font-size: 0.9em;
line-height: 1.45;
}
@media (max-width: 900px) {
.s7-tech-embed .process-stages {
grid-template-columns: 1fr;
}
}
@media (max-width: 600px) {
.s7-tech-embed .process-branches {
grid-template-columns: 1fr;
}
}
</style><div class="process-flow" aria-label="VX/JSP submission and print dispatch flow"><div class="process-stages"><div class="process-stage"><span class="process-number">01</span><strong>SUBMIT or PRINT</strong><span>VX/DCL parses the verb, qualifiers, and parameters.</span></div><div class="process-stage"><span class="process-number">02</span><strong>SYS$SNDJBC</strong><span>Builds the job stream and writes its record to the <code>.JOBS</code> file.</span></div><div class="process-stage"><span class="process-number">03</span><strong>jspctl controller</strong><span>A shared <code>RequestRecord</code> signals the controller, which routes the request to <code>QueueControl</code>.</span></div><div class="process-stage"><span class="process-number">04</span><strong>qmgr queue worker</strong><span>The controller sends the queue request over its FIFO and <code>start_job</code> selects the work.</span></div><div class="process-stage"><span class="process-number">05</span><strong>pjob symbiont</strong><span>A per-job worker starts and follows the print or batch branch.</span></div></div><div class="process-branches" aria-label="Symbiont output branches"><div class="process-stage process-branch"><span class="process-label">Print branch</span><strong>Print file</strong><span>The symbiont sends the queued file to the configured output device.</span></div><div class="process-stage process-branch"><span class="process-label">Batch branch</span><strong>Execute command procedure</strong><span>The symbiont runs the queued <code>.COM</code> file through VX/DCL.</span></div></div></div><h6>Process lifecycle</h6><p>
The three daemons share one fixed startup pattern. Each of <code>jspctl</code>,
<code>qmgr</code> and <code>pjob</code> runs the same six phases in order: initialise, open the
log, attach the spool area, start, enter the main loop, and finalise on shutdown.
</p><h2 id="data-model">Queue files and data model</h2><p>
VX/JSP recreates the OpenVMS queue database as flat, fixed-record, packed files under the
spool directory (<code>SYS$SPOOL:[jsp]</code> by default). There is no RMS on Linux, so records
are accessed directly and locked with <code>fcntl</code> record locks. Each VMS queue-database
file maps to a VX/JSP file with the same role.
</p><div class="table-wrapper"><table><thead><tr><th>OpenVMS file</th><th>VX/JSP file</th><th>Holds</th></tr></thead><tbody><tr><td><code>QMAN$MASTER.DAT</code></td><td><code>QMAN$MASTER</code></td><td>Cluster and manager master record.</td></tr><tr><td>Controller channel</td><td><code>QMAN$JSPCTL</code></td><td>Controller request endpoint.</td></tr><tr><td>Queue list</td><td><code>QMAN$QUEUES</code></td><td>One queue record per queue.</td></tr><tr><td>Form list</td><td><code>QMAN$FORMS</code></td><td>One form record per form.</td></tr><tr><td>Per-queue manager</td><td><code>QMAN$MANAGER</code></td><td>Live queue-manager state for the queue.</td></tr><tr><td>Per-queue jobs</td><td><code>QMAN$JOBS</code></td><td>One job record per queue entry.</td></tr></tbody></table></div><h6>Records</h6><p>
The three core record classes preserve the OpenVMS field semantics so that queue, job and form
attributes survive migration byte for byte:
</p><ul><li><strong>Queue record.</strong> Carries the queue name, node name and server address, the
process id, manager and queue status flags, default and mounted form numbers, job count and
job limit, base, standard and active priorities, owner, device, processor and library names,
a generic-queue routing list, and a description.</li><li><strong>Job record.</strong> Carries the entry number (which replaces the VMS job id), job
status and flags, the VMS exit status, submitting user uid and gid, form number, copy count,
page ranges, up to eight DCL parameters, submit, after and until times, the log file and
working directory, and a per-file array (up to 16 files per job) with each file's name,
status, page range and copy counts.</li><li><strong>Form record.</strong> Carries the form number, length and width, top, bottom, left
and right margins, flags, description, page-setup and setup names, and stock.</li></ul><h6>Job record state byte</h6><p>The state byte on each job record tracks where the entry is in its lifecycle.</p><div class="table-wrapper"><table><thead><tr><th>Symbol</th><th>Value</th><th>Meaning</th></tr></thead><tbody><tr><td><code>QMGR_VIRGIN</code></td><td><code>0x00</code></td><td>Free / unused record.</td></tr><tr><td><code>QMGR_REQUEUED</code></td><td><code>0xfb</code></td><td>Requeued job.</td></tr><tr><td><code>QMGR_CHECK</code></td><td><code>0xfc</code></td><td>Needs an operator-message check.</td></tr><tr><td><code>QMGR_STOPPED</code></td><td><code>0xfd</code></td><td>Stopped.</td></tr><tr><td><code>QMGR_INUSE</code></td><td><code>0xfe</code></td><td>In use.</td></tr><tr><td><code>QMGR_DELETED</code></td><td><code>0xff</code></td><td>Deleted.</td></tr></tbody></table></div><div class="callout"><strong>Record locking.</strong> Queue and job records are read and updated in place under
<code>fcntl</code> locks with explicit wait, no-wait, for-update and for-owning options, so
concurrent queue managers and clients coordinate the same way VMS coordinated access to the
queue database.
</div><h2 id="services">SYS$ system services</h2><p>
Applications that already drive OpenVMS queues call two system services, and VX/JSP implements
both with VMS-compatible function and item code tables. Existing calls link and run without API
changes; the COBOL <code>SYS$</code> wrappers forward to the same runtime entry points.
</p><h6>SYS$SNDJBC and SYS$SNDJBCW</h6><p><code>SYS$SNDJBC</code> sends a request to the job controller: it submits and controls jobs, and
creates, alters and controls queues. Requests carry a function code plus an item list. The
service supports the full VMS function range; the operation codes below are a representative
subset of those implemented.
</p><div class="table-wrapper"><table><thead><tr><th>Code</th><th>Operation</th><th>Code</th><th>Operation</th></tr></thead><tbody><tr><td>1</td><td><code>ABORT_JOB</code></td><td>18</td><td><code>DELETE_QUEUE</code></td></tr><tr><td>2</td><td><code>ADD_FILE</code></td><td>19</td><td><code>ENTER_FILE</code></td></tr><tr><td>3</td><td><code>ALTER_JOB</code></td><td>20</td><td><code>MERGE_QUEUE</code></td></tr><tr><td>4</td><td><code>ALTER_QUEUE</code></td><td>21</td><td><code>PAUSE_QUEUE</code></td></tr><tr><td>5</td><td><code>ASSIGN_QUEUE</code></td><td>22</td><td><code>RESET_QUEUE</code></td></tr><tr><td>9</td><td><code>CLOSE_JOB</code></td><td>24</td><td><code>START_QUEUE</code></td></tr><tr><td>10</td><td><code>CREATE_JOB</code></td><td>25</td><td><code>START_QUEUE_MANAGER</code></td></tr><tr><td>11</td><td><code>CREATE_QUEUE</code></td><td>27</td><td><code>STOP_QUEUE</code></td></tr><tr><td>13</td><td><code>DEFINE_CHARACTERISTIC</code></td><td>28</td><td><code>STOP_QUEUE_MANAGER</code></td></tr><tr><td>14</td><td><code>DEFINE_FORM</code></td><td>29</td><td><code>SYNCHRONIZE_JOB</code></td></tr><tr><td>16</td><td><code>DELETE_FORM</code></td><td>35</td><td><code>DISABLE_QUEUE</code></td></tr><tr><td>17</td><td><code>DELETE_JOB</code></td><td>36</td><td><code>ENABLE_QUEUE</code></td></tr></tbody></table></div><p>
Input item codes cover the job and queue attributes an application sets when submitting or
altering work, such as after-time, base priority, batch flag, characteristic name, checkpoint
data and command-language interpreter. Return status uses the standard VMS <code>JBC$</code>
status codes, for example normal completion, invalid function code, invalid item code and
empty job.
</p><h6>SYS$GETQUI and SYS$GETQUIW</h6><p><code>SYS$GETQUI</code> queries queue, job, file and form information. It supports ten function
codes over a large item-code space, and this is the service behind <code>SHOW QUEUE</code> and
the <code>qmon</code> monitor.
</p><div class="table-wrapper"><table><thead><tr><th>Code</th><th>Function</th></tr></thead><tbody><tr><td>1</td><td><code>CANCEL_OPERATION</code> - cancel a wildcard operation.</td></tr><tr><td>2</td><td><code>DISPLAY_CHARACTERISTIC</code></td></tr><tr><td>3</td><td><code>DISPLAY_FILE</code></td></tr><tr><td>4</td><td><code>DISPLAY_FORM</code></td></tr><tr><td>5</td><td><code>DISPLAY_JOB</code></td></tr><tr><td>6</td><td><code>DISPLAY_QUEUE</code></td></tr><tr><td>7</td><td><code>TRANSLATE_QUEUE</code></td></tr><tr><td>8</td><td><code>DISPLAY_ENTRY</code></td></tr><tr><td>9</td><td><code>DISPLAY_QMAN</code></td></tr><tr><td>10</td><td><code>DISPLAY_MANAGER</code></td></tr></tbody></table></div><div class="callout"><strong>Source compatibility.</strong> Because the function codes, item codes and status
values match OpenVMS, an application that calls <code>SYS$SNDJBC</code> or
<code>SYS$GETQUI</code> for queue and job control keeps working after migration without any
change to its service calls.
</div><h2 id="commands">DCL command surface</h2><p>
VX/JSP is driven entirely through VX/DCL verbs, so the queue commands operators already know
work unchanged. All major VMS queue-management commands are supported, and no syntax changes
are required for migrated workloads.
</p><div class="table-wrapper"><table><thead><tr><th>Command</th><th>Description</th></tr></thead><tbody><tr><td><code>INITIALIZE/QUEUE</code></td><td>Initialize a new queue.</td></tr><tr><td><code>DEFINE/FORM</code></td><td>Set up form definitions (margins, stock, page setup).</td></tr><tr><td><code>START/QUEUE</code></td><td>Start a queue.</td></tr><tr><td><code>START/QUEUE/MANAGER</code></td><td>Start the queue manager.</td></tr><tr><td><code>SUBMIT</code></td><td>Submit a batch job.</td></tr><tr><td><code>PRINT</code></td><td>Submit a print job.</td></tr><tr><td><code>SET QUEUE</code> / <code>SET/ENTRY</code></td><td>Modify queue attributes or a queued entry.</td></tr><tr><td><code>SHOW QUEUE</code> / <code>SHOW QUEUE/FORM</code></td><td>Display queue or form status.</td></tr><tr><td><code>DELETE/ENTRY</code></td><td>Remove a job from the queue.</td></tr><tr><td><code>DELETE/FORM</code>, <code>DELETE/QUEUE</code></td><td>Remove a form or a queue.</td></tr><tr><td><code>STOP/QUEUE</code> (<code>/ABORT</code>, <code>/ENTRY</code>, <code>/MANAGER</code>)</td><td>Stop a queue, abort work, stop an entry, or stop the manager.</td></tr><tr><td><code>SYNCHRONIZE</code></td><td>Wait for a job to complete.</td></tr></tbody></table></div><h6>Qualifiers</h6><p>
The queue and job commands carry the OpenVMS qualifier sets, covering print, batch and
queue/form definition. The source-visible qualifiers include:
</p><ul><li><strong><code>INITIALIZE/QUEUE</code>:</strong> <code>/BASE_PRIORITY</code>,
<code>/BATCH</code>, <code>/BURST</code>, <code>/DEFAULT</code>, <code>/FEED</code>,
<code>/FORM</code>, <code>/FORM_MOUNTED</code>, <code>/JOB_LIMIT</code>, <code>/ON</code>,
<code>/PRIORITY</code>, <code>/START</code>, <code>/STOCK</code>, <code>/TRAILER</code>.</li><li><strong><code>PRINT</code>:</strong> <code>/AFTER</code>, <code>/COPIES</code>,
<code>/DELETE</code>, <code>/FEED</code>, <code>/FORM</code>, <code>/HEADER</code>,
<code>/HOLD</code>, <code>/NOTIFY</code>, <code>/PRIORITY</code>, <code>/QUEUE</code>,
<code>/SETUP</code>, <code>/STOCK</code>, <code>/TRAILER</code>.</li><li><strong><code>SUBMIT</code>:</strong> <code>/AFTER=time</code>, <code>/DELETE</code>,
<code>/HOLD</code>, <code>/[NO]KEEP</code>, <code>/NOTIFY</code>,
<code>/PARAMETERS=(p1..p8)</code>, <code>/PRINTER[=queue]</code>,
<code>/QUEUE=queue</code> (default <code>SYS$BATCH</code>).</li></ul><h6>Worked example: submit a batch job</h6><p>Submitting a DCL command file and checking its status, using the site's demo batch queue:</p>
<pre>$ <span class="kw">submit</span>/notify/queue=sys$batch/print/nokeep FUNDS_TRANSFER.COM
Job FUNDS_TRANSFER.COM pending on SYS$BATCH, entry 2
$
$ <span class="kw">show queue</span>/full/all sys$batch
Batch queue SYS$BATCH, running
/PRIORITY=0 /NOENABLE_GENERIC
/JOB_LIMIT=1
Jobname Username Entry Status
------- -------- ----- ------
FUNDS_TRANSFER.COM batchop 2 executing
Job FUNDS_TRANSFER.COM (queue SYS$BATCH, entry 2) completed.
$</pre>
<h6>Sample queue display output</h6><p>
VX/JSP retains the VMS queue listing format, so operators see familiar output. The
<code>qmon</code> monitor prints queues (<code>Q:</code>) and jobs (<code>J:</code>) with their
record numbers, process ids, owners and status:
</p>
<pre> --- locks ---
rec# job# name pid own upd status
Q: 0 0 JSPCTL 18053 18053 0 running - available jobs 0 max 0
Q: 1 1 SYS$BATCH 18056 18056 0 running - idle,available jobs 5 max 5
J: 6 6 EVENT_6 18283 18277 0 Executing 18277 00040001
J: 11 11 EVENT_11 0 0 0 Pending 0 00040001
5 of 7 jobs executing
Q: 2 2 SYS$PRINT 18059 18059 0 running - idle,available jobs 1 max 1
4 queue records, 14 job records, 6 executing</pre>
<h2 id="symbiont">Print and batch symbiont</h2><p>
The <code>pjob</code> symbiont is the per-job worker. When a queue starts a job, the symbiont
dispatches on the queue type: for a batch job it executes the DCL command file within VX/DCL;
for a print job it runs the VMS page-formatting pipeline and sends the output to a device.
</p><h6>Batch path</h6><p>
A batch job runs its command file exactly as it did on OpenVMS. The original DCL syntax is
retained, so existing <code>.COM</code> procedures migrate without modification. Submitting
users' uid and gid are honoured, queue priorities and scheduling intervals control execution,
and a single queue can run multiple jobs at once up to its job limit.
</p><h6>Print path</h6><p>
The print path reproduces the VMS symbiont behaviour: form setup and load, page geometry
(headers, trailers, feeds, page ranges), burst and flag pages, and carriage-control fixup that
converts VMS record formatting to the target stream. Setup modules and text libraries are
supported through the <code>/SETUP</code> and <code>/LIBRARY</code> qualifiers. Print jobs can
restart on a specific page, and queues support reordering and job prioritization.
</p><div class="callout"><strong>External symbionts.</strong> A customer print symbiont image can be loaded through
the <code>/PROCESSOR=</code> qualifier, matching the VMS mechanism for site-specific device
handling.
</div><h6>Networked printing</h6><p>
Printing to physical devices maps VMS devices to their Linux equivalents. Jobs can print to
locally connected devices or spoolers, to direct printer connections, or to mapped network
printers. A print-device layer handles host and port connections with PCL and PJL detection,
and dedicated symbionts cover terminal-server (telnet) and Xerox devices.
</p><div class="table-wrapper"><table><thead><tr><th>Target</th><th>Mechanism</th></tr></thead><tbody><tr><td>Local device or spooler</td><td>Direct file or device output from <code>pjob</code>.</td></tr><tr><td>Network printer (raw)</td><td>TCP connection to the device, default port 9100, with PCL/PJL support.</td></tr><tr><td>Terminal-server printer</td><td><code>telnetsym</code> prints over TCP to a telnet terminal server.</td></tr><tr><td>Xerox device</td><td><code>libxrxsym</code> loadable device symbiont.</td></tr></tbody></table></div><h6>Forms</h6><p>
Forms are first-class: <code>DEFINE/FORM</code> records margins, length, width, stock and
page-setup names, and the <code>form_read</code> tool dumps form records for inspection. Queues
carry a default and a mounted form, so form-based print layouts migrate with the queue
definitions that reference them.
</p><h2 id="compatibility">Compatibility and divergences</h2><p>
The core spooling subsystem is complete and source-compatible. The matrix summarises what is
live today and where behaviour is scoped or still maturing.
</p><div class="table-wrapper"><table><thead><tr><th>Capability</th><th>Status</th></tr></thead><tbody><tr><td>Job-controller daemon (<code>jspctl</code>)</td><td><span class="ac-live">live</span></td></tr><tr><td>Per-queue manager and scheduler (<code>qmgr</code>)</td><td><span class="ac-live">live</span></td></tr><tr><td>Print and batch symbiont (<code>pjob</code>)</td><td><span class="ac-live">live</span></td></tr><tr><td><code>SYS$SNDJBC</code> / <code>SYS$SNDJBCW</code></td><td><span class="ac-live">live</span></td></tr><tr><td><code>SYS$GETQUI</code> / <code>SYS$GETQUIW</code></td><td><span class="ac-live">live</span></td></tr><tr><td>COBOL <code>SYS$</code> wrappers</td><td><span class="ac-live">live</span></td></tr><tr><td>DCL commands (SUBMIT, PRINT, SHOW QUEUE, and more)</td><td><span class="ac-live">live</span></td></tr><tr><td>Forms (<code>DEFINE/FORM</code>, margins, stock)</td><td><span class="ac-live">live</span></td></tr><tr><td>Networked printing (TCP 9100, PCL, PJL)</td><td><span class="ac-live">live</span></td></tr><tr><td>Xerox device symbiont</td><td><span class="ac-live">live</span></td></tr><tr><td>Terminal-server (telnet) symbiont</td><td><span class="ac-v1">built on demand</span></td></tr><tr><td>Queue and job monitor GUI (<code>qmon</code>)</td><td><span class="ac-live">live text</span> <span class="ac-v1">GUI optional (X11/Qt)</span></td></tr><tr><td>Queue-record repair (<code>qfix</code>)</td><td><span class="ac-live">live</span></td></tr><tr><td>Generic / logical queue routing</td><td><span class="ac-v1">partial</span></td></tr><tr><td>Cluster / multi-node queues</td><td><span class="ac-v2">fields present, clustering not enabled</span></td></tr></tbody></table></div><h6>Divergences from OpenVMS</h6><p>
VX/JSP preserves external behaviour while substituting Linux facilities for VMS internals where
there is no direct equivalent.
</p><div class="table-wrapper"><table><thead><tr><th>OpenVMS mechanism</th><th>VX/JSP on Linux</th></tr></thead><tbody><tr><td>RMS <code>QMAN$*.DAT</code> files</td><td>Flat, fixed-record, packed files under the spool directory, accessed directly and <code>fcntl</code>-locked.</td></tr><tr><td>VMS job id (jid)</td><td>Job entry number that preserves external entry semantics without the VMS internal encoding.</td></tr><tr><td>VMS privilege model</td><td>setuid-root controller, or <code>cap_setuid</code>/<code>cap_setgid</code> capabilities, to run jobs as the submitting user.</td></tr><tr><td>VMS mailbox IPC</td><td>FIFOs plus a shared request record between controller, queue managers and symbionts.</td></tr><tr><td>Single-threaded VMS queue manager</td><td>POSIX-threaded queue worker (up to 300 active jobs).</td></tr><tr><td>LAT / <code>LATSYM</code> printing</td><td>TCP terminal-server printing plus raw-9100 and PCL device output.</td></tr><tr><td>DECwindows <code>SHOW QUEUE</code> UI</td><td>X11/Xt (optionally Qt) <code>qmon</code> monitor.</td></tr></tbody></table></div><h2 id="quick-reference">Quick reference</h2><h6>Processes and tools</h6><div class="kw-grid"><div>jspctl (controller)</div><div>qmgr (per queue)</div><div>pjob (symbiont)</div><div>qmon (monitor)</div><div>qfix (repair)</div><div>jspmgr (status probe)</div><div>form_read (form dump)</div><div>telnetsym (TCP printing)</div><div>libxrxsym (Xerox)</div></div><h6>Queue files (spool directory)</h6><div class="kw-grid"><div>QMAN$MASTER</div><div>QMAN$QUEUES</div><div>QMAN$FORMS</div><div>QMAN$JSPCTL</div><div>QMAN$MANAGER</div><div>QMAN$JOBS</div></div><h6>System services</h6><ul><li><code>SYS$SNDJBC</code> / <code>SYS$SNDJBCW</code> - submit and control jobs; create and control queues.</li><li><code>SYS$GETQUI</code> / <code>SYS$GETQUIW</code> - query queue, job, file and form information (10 function codes).</li></ul><h6>Key DCL verbs</h6><div class="kw-grid"><div>INITIALIZE/QUEUE</div><div>START/QUEUE</div><div>START/QUEUE/MANAGER</div><div>SUBMIT</div><div>PRINT</div><div>SET QUEUE</div><div>SET/ENTRY</div><div>SHOW QUEUE</div><div>DEFINE/FORM</div><div>DELETE/ENTRY</div><div>STOP/QUEUE</div><div>SYNCHRONIZE</div></div><h6>Limits</h6><div class="table-wrapper"><table><thead><tr><th>Limit</th><th>Value</th></tr></thead><tbody><tr><td>Files per job</td><td>16</td></tr><tr><td>DCL parameters per job</td><td>8</td></tr><tr><td>Active jobs per queue</td><td>300</td></tr><tr><td>Scheduled jobs</td><td>10000</td></tr><tr><td>Queue name length</td><td>32</td></tr><tr><td>Job name length</td><td>48</td></tr></tbody></table></div><h6>Build and install</h6><p>
VX/JSP builds with the standard Linux toolchain: <code>g++</code> and <code>gcc</code>, POSIX
threads, <code>fcntl</code> record locks and BSD sockets, with an optional X11/Xt (or Qt) build
for the <code>qmon</code> GUI. Install places the controller and workers setuid root, or grants
the equivalent Linux capabilities.
</p></div>