====== Lynx 2.9.3 on OpenVMS VAX: multi-user install, bookmarks and HTTPS ======
Installing the Lynx VMSINSTAL kit so it works for **every** user, giving each
user their own bookmarks as their start page, and getting ''https:'' working
without SSL. Verified on ''OpenVMS VAX V7.3'' (node ''GOZER''), ''Lynx 2.9.3''
built with ''DEC C'', TCP/IP Services (UCX).
**The single fact this whole page turns on: a logical name can be system-wide,
a DCL symbol cannot.** Lynx needs both — ''Lynx_Dir'' is a logical, ''LYNX'' is
a symbol — so the startup procedure has to run in two different places.
===== Quick Reference =====
^ Task ^ Command ^
| Install the kit | ''@SYS$UPDATE:VMSINSTAL LYNX293 DKA0:[LYNX293.KIT]'' |
| Enable for this process | ''@SYS$MANAGER:LYNX$STARTUP'' |
| Check the system logical | ''SHOW LOGICAL/SYSTEM LYNX_DIR'' |
| Check the command symbol | ''SHOW SYMBOL LYNX'' |
| Check a user's start page | ''SHOW LOGICAL WWW_HOME'' |
| Add a bookmark, in Lynx | ''a'' then ''d'' then Enter |
| View bookmarks, in Lynx | ''v'' |
| Run as another user, no password | ''SUBMIT/USER=ABLACK/LOG_FILE=...'' |
| Check a file's record format | ''DIRECTORY/FULL file.html'' |
| Rebuild the kit | ''@MAKE_KIT'' from ''DKA0:[LYNX293.KIT]'' |
===== Making Lynx available to every user =====
Two edits. Neither substitutes for the other, and doing only one is why an
install looks like it worked for ''SYSTEM'' alone.
**# For the system-wide Lynx_Dir logical, in SYS$MANAGER:SYSTARTUP_VMS.COM:**
@SYS$MANAGER:LYNX$STARTUP
**# For the LYNX symbol, in SYS$MANAGER:SYLOGIN.COM:**
@SYS$MANAGER:LYNX$STARTUP
The same line in both files. The procedure works out which half to do:
''Lynx_Dir'' is defined ''/SYSTEM'' when the caller holds ''SYSNAM'', and the
symbol is defined every time.
There is no ''DEFINE/SYSTEM'' for symbols. That is not a limitation to work
around — it is why the ''SYLOGIN.COM'' edit is mandatory.
**# Confirm the logical really is system-wide, not just yours:**
SHOW LOGICAL/SYSTEM LYNX_DIR
''%SHOW-S-NOTRAN, no translation for logical name LYNX_DIR'' is the whole bug
in one line. It means only the account that ran the startup procedure has Lynx.
==== Testing as an unprivileged user without their password ====
''SUBMIT/USER='' needs ''CMKRNL'', which ''SYSTEM'' has. Batch jobs execute
''SYLOGIN.COM'', so this exercises the real login path.
**# Run a test procedure as another account:**
SUBMIT/USER=ABLACK/LOG_FILE=DKA0:[ABLACK]TEST.LOG/NOPRINTER DKA0:[LYNX293.KIT]TEST.COM
The test account used here was ''ABLACK'', UIC ''[200,20]'', authorised
privileges ''NETMBX'' and ''TMPMBX'' only. If Lynx works there it works for
anyone.
===== Per-user bookmarks as the start page =====
Each user gets their own bookmark file with no setup. Lynx prepends the home
directory — ''SYS$LOGIN'' on VMS — to ''DEFAULT_BOOKMARK_FILE''.
DEFAULT_BOOKMARK_FILE:lynx_bookmarks.html
It **must** stay a bare filename. An absolute path there gives the whole system
one shared file.
Startfile precedence in Lynx is:
* command line
* ''WWW_HOME''
* ''STARTFILE'' in ''lynx.cfg''
So defining ''WWW_HOME'' at login makes a user's own bookmarks their start page
while ''LYNX http://host/'' still goes where it was told.
**# What LYNX$STARTUP.COM defines, per user:**
DEFINE/NOLOG WWW_HOME "file://localhost/SYS$LOGIN:LYNX_BOOKMARKS.HTML"
The quotes matter twice: Lynx looks up the **lowercase** name, and a logical
name works inside a ''file:'' URL.
==== The four gotchas that will waste your afternoon ====
**# 1. "BOOKMARK_FILE" is not a lynx.cfg keyword.**
Only ''DEFAULT_BOOKMARK_FILE'' exists. A ''BOOKMARK_FILE:'' line is read,
not recognised, and discarded with no warning at all. It looks like it works.
**# 2. Do not use "lynx -book" to make bookmarks the start page.**
It looks like exactly the right answer — the help text even says "use the
bookmark page as the startfile". But it **also overrides a URL given on the
command line**, so with ''-book'' in the ''LYNX'' symbol,
''LYNX http://example.com/'' silently opens bookmarks instead. Use ''WWW_HOME''.
''-book'' is still fine to type by hand.
**# 3. The bookmark file must be Stream_LF, or Lynx duplicates its own header.**
This is the expensive one. Lynx appends a bookmark by reopening the file
''"a+"'', rewinding, and re-reading it to find where to insert. On a
**variable-length record** file that read comes back empty, so Lynx concludes
the file is new and writes a second complete copy of the header, stranding the
bookmarks after it.
DCL ''CREATE'', ''OPEN/WRITE'' and ''COPY'' from a text file all produce
variable-record files. Lynx itself writes Stream_LF.
**# Check any bookmark file you made by hand:**
DIRECTORY/FULL SYS$LOGIN:LYNX_BOOKMARKS.HTML
''Record format: Stream_LF'' is what you need.
**# Convert a variable-record file to Stream_LF:**
CONVERT/FDL=BOOKSKEL.FDL BOOKSKEL.HTML LYNXBOOK.HTML
FILE
ORGANIZATION sequential
RECORD
CARRIAGE_CONTROL carriage_return
FORMAT stream_lf
''BACKUP'', ''VMSINSTAL'' and ''COPY'' all preserve the record format, so
converting once at kit-build time is enough.
**# 4. WWW_HOME cannot point at a file that does not exist.**
Lynx quits with ''lynx: Can't access startfile''. So the startup procedure
seeds an empty bookmark file into the user's ''SYS$LOGIN'' on first login.
Without that seed there is an off-by-one login: the procedure runs **before**
the user has added anything, so the first bookmark only shows up at their
//next// login.
===== "Can't access startfile" is usually a protection problem =====
Can't Access `file://localhost/sys$common:[lynx]bookmarks.html'
Alert!: Unable to access document.
lynx: Can't access startfile
The instinct is to blame the URL syntax. It is almost always the file
protection. A page in ''SYS$COMMON:[LYNX]'' that every user must open needs
''World:RE''; files put there by hand land as ''(RWED,RWED,RE,)'' and only the
owner can read them.
**# Fix a shared page nobody else can read:**
SET PROTECTION=(S:RWED,O:RWED,G:RE,W:RE) SYS$COMMON:[LYNX]BOOKMARKS.HTML
Proven by direct comparison: two files in that directory, same URL form, both
present — the ''World:RE'' one rendered for an unprivileged account and the
''World:'' one produced exactly the message above.
==== Which file: URL forms actually work ====
^ Form ^ Works ^
| ''file://localhost/DKA0:[DIR]FILE.HTML'' | yes |
| ''file://localhost/SYS$LOGIN:FILE.HTML'' | yes |
| ''file://localhost/SYS$COMMON:[LYNX]FILE.HTML'' | yes |
| ''file://localhost/Lynx_Dir:FILE.HTML'' | yes |
| ''file://localhost/~/FILE.HTML'' | **no** |
Logical names are fine, including rooted concealed ones. The ''~/'' form is
not: Lynx expands it to a doubled slash and cannot open the result.
Prefer ''Lynx_Dir:'' in ''lynx.cfg'' — it stays correct wherever the kit was
installed.
===== HTTPS through a gateway proxy =====
No SSL in this build, so on its own:
Alert!: This client does not contain support for HTTPS URLs.
A proxy fixes it, but **only a TLS-terminating gateway**. Lynx sends the proxy
a plain-HTTP absolute-URI request — literally ''GET https://host/path HTTP/1.0''
over an unencrypted connection — and expects the page back in clear. It never
sends ''CONNECT'': that code in ''HTTP.c'' is inside ''#ifdef USE_SSL'' and is
not compiled in. A stock Squid, which serves ''https:'' by tunnelling
''CONNECT'', cannot work here however it is configured.
**# Test a candidate proxy before trusting it — 200 means it will work:**
printf 'GET https://example.com/ HTTP/1.0\r\n\r\n' | nc 172.24.9.10 5001
''405'' or a CONNECT-only answer means it will not.
**# Set it for every user and every mode, in lynx.cfg:**
https_proxy:http://172.24.9.10:5001/
Only ''https:'' is proxied; plain ''http:'' keeps going out directly.
**# Override it for one session — lowercase, so quoted on VMS:**
DEFINE "https_proxy" "http://otherproxy:8080/"
**# Turn proxying off for one session:**
DEFINE "no_proxy" "*"
Logicals take precedence over ''lynx.cfg''.
===== Rebuilding the kit =====
**# From the kit directory, after a successful build:**
@MAKE_KIT
Four details in ''MAKE_KIT.COM'' are load-bearing.
**# 1. BACKUP takes ALL versions unless you say ";0".**
Without it a second build ships ''KITINSTAL.COM;2'' //and// '';1'', and
VMSINSTAL restores both.
BACKUP KITINSTAL.COM;0,LYNX$STARTUP.COM;0,... LYNX293.A/SAVE_SET/BLOCK_SIZE=2048
**# 2. /BLOCK_SIZE=2048 is not optional.**
BACKUP's disk default of 32256 makes VMSINSTAL misframe the save set; it fails
at restore with ''INVBLKSIZE'' or CRC errors.
**# 3. COPY takes the HIGHEST version, which may not be the one you want.**
A tree used for testing easily has a hand-made three-line ''LYNX.CFG'' sitting
on top of the real 320-block one. Ship that by accident and every installation
gets a three-line config. ''MAKE_KIT.COM'' now prints the block counts it
picked up and refuses to build if they are implausible.
**# 4. Bring the save set back in IMAGE mode, then repair the attributes.**
A save set that has been through FTP or a zip arrives on VMS as a stream file
and BACKUP will not read it.
SET FILE/ATTRIBUTES=(RFM:FIX,MRS:2048,LRL:2048,RAT:NONE) LYNX293.A
===== SYS$MANAGER is a search list =====
Worth knowing before you edit ''SYLOGIN.COM'' with anything that writes a new
file rather than a new version — including DCL ''OPEN/WRITE''. It reads the
copy in ''SYS$COMMON:[SYSMGR]'' but creates its output in
''SYS$SPECIFIC:[SYSMGR]'', which then silently shadows the real one.
**# Name the common copy explicitly:**
COPY SYS$COMMON:[SYSMGR]SYLOGIN.COM SYS$COMMON:[SYSMGR]SYLOGIN.COM;
**# Confirm you left no shadow behind — %DIRECT-W-NOFILES is the answer you want:**
DIRECTORY SYS$SPECIFIC:[SYSMGR]SYLOGIN.COM
A ''SYLOGIN.COM'' created without ''World:RE'' locks every non-privileged user
out at login. Always stamp the protection after writing it.
===== Troubleshooting =====
^ Symptom ^ Cause ^ Fix ^
| ''%DCL-W-IVVERB'' on ''LYNX'' for some users | symbol is per-process; ''SYLOGIN.COM'' edit missing | add ''@SYS$MANAGER:LYNX$STARTUP'' to ''SYLOGIN.COM'' |
| ''Configuration file "Lynx_Dir:lynx.cfg" is not available'' | ''Lynx_Dir'' not defined ''/SYSTEM'' | add the same line to ''SYSTARTUP_VMS.COM'' |
| ''%SHOW-S-NOTRAN'' for ''LYNX_DIR'' | logical was defined per-process only | ''DEFINE/SYSTEM/NOLOG Lynx_Dir SYS$COMMON:[LYNX]'' |
| ''lynx: Can't access startfile'' | target file is not ''World:RE'' | ''SET PROTECTION=(S:RWED,O:RWED,G:RE,W:RE)'' |
| Bookmark file has the header twice | file is variable-record, not Stream_LF | rebuild it with ''CONVERT/FDL'' |
| First bookmark does not appear on the start page | no seed file, so ''WWW_HOME'' was not defined at login | seed an empty bookmark file at first login |
| ''LYNX http://host/'' opens bookmarks instead | ''-book'' is in the ''LYNX'' symbol | remove it; use ''WWW_HOME'' |
| ''This client does not contain support for HTTPS URLs'' | no ''https_proxy'', or a CONNECT-only proxy | use a TLS-terminating gateway |
| ''%COPY-W-INCOMPAT'' when appending to a config | mixed record formats | harmless for text; check the result with ''DIRECTORY/FULL'' |
| Edits to ''SYLOGIN.COM'' seem to vanish | shadow file in ''SYS$SPECIFIC:[SYSMGR]'' | delete it, edit ''SYS$COMMON:'' explicitly |
| ''INVBLKSIZE'' or CRC error at VMSINSTAL restore | save set arrived as a stream file | ''SET FILE/ATTRIBUTES=(RFM:FIX,MRS:2048,LRL:2048,RAT:NONE)'' |
===== Where things live =====
^ File ^ Location ^
| Browser image | ''SYS$SYSTEM:LYNX.EXE'' |
| Global config | ''SYS$COMMON:[LYNX]LYNX.CFG'' |
| Default start page | ''SYS$COMMON:[LYNX]LYNXSTART.HTML'' |
| Bookmark skeleton | ''SYS$COMMON:[LYNX]LYNXBOOK.HTML'' |
| Per-user bookmarks | ''SYS$LOGIN:LYNX_BOOKMARKS.HTML'' |
| Startup procedure | ''SYS$MANAGER:LYNX$STARTUP.COM'' |
| VMS help text | ''SYS$HELP:LYNX.HLP'' |
| Kit source | ''DKA0:[LYNX293.KIT]'' |
Rule of thumb: **if something works for ''SYSTEM'' and nobody else, you have a
scope problem — check whether it is a logical or a symbol, and check the
World protection.**