====== 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.**