Chapter 2. Installing HTTPD
This chapter installs HTTPD on an MVS 3.8j system (TK4-, TK5, MVS/CE or a Hercules build of your own) from the release package. The installation is done by SMP Release 4, the SMP that comes with MVS 3.8j, not SMP/E. SMP keeps a record of what was installed. So there is a defined way to replace it with the next release (Chapter 10, “Upgrading HTTPD”) and a defined way to take it out (Chapter 11, “Removing HTTPD”).
The captures in this chapter come from a first install of release 4.5.1 on a TK5 system, with one exception that the text names: the RAKF captures come from MVS/CE. The package was built from the source of the release branch, with the version in the project file changed from 4.5.1-dev to 4.5.1. The build stamp in the start-up banner is therefore not the one of the published package (“Starting HTTPD”). Every step of the install job ended with return code 0000, HTTPD.LINKLIB and HTTPD.AHTTPLOD each held the five load modules, and the SMP record showed the FMID THTP451. The file names in your package carry the number of your release. The steps do not change from one release to the next.
Report a problem as an issue at https://github.com/mvslovers/httpd/issues. Add the two build stamps that HTTPD writes at the start (HTTPD000I and HTTPD005I, “Starting HTTPD”), the console messages and, for an installation problem, the job output. Questions go to the Discord server of the project.
The names of the data sets carry no version. HTTPD.LINKLIB is the same name in every release. The STEPLIB of the procedure and an APF entry are written once. The price is that two releases cannot be installed side by side. An upgrade replaces what is there, and there is no way back to the previous release: the install job accepts the new level, and SMP refuses a RESTORE of an accepted function.
The installation is a sequence of tasks. Each one has a goal, what you type, what comes back and what can go wrong:
- Read what is in the package (“What Is in the Package”) and what the system needs (“What You Need”).
- Send the two XMIT files to MVS (“Sending the Two XMIT Files”).
- Stop a running HTTPD, if there is one (“Stopping a Running HTTPD”).
- Allocate the product data sets (“Allocating the Product Data Sets”).
- Edit and submit the install job (“Editing and Submitting the Install Job”), read the result (“Reading the Result”) and verify the work (“Verifying the Install”).
- Put the procedure and the Parmlib member in place (“The Procedure and the Parmlib Member”).
- Define the user and the profiles in RAKF (“Defining the Users and Profiles in RAKF”).
- Put the webroot disk on the system and mount it (“The Document Root Disk”).
- Start HTTPD (“Starting HTTPD”).
If this system already runs an older HTTPD, do not use this chapter. Use Chapter 10, “Upgrading HTTPD”. The FMID of this release, THTP451, deletes THTP450 and nothing else (“One Release at a Time”).
What Is in the Package
The package is the archive httpd-4.5.1-dist.zip (or httpd-4.5.1-dist.tar.gz). It has six files. In their names, 4.5.1 is the release. The webroot image has no version in its name.
| File | What it is |
README.md | The installation guide as a text file. |
httpd-4.5.1-load.xmit | The five load modules, in a form that TSO RECEIVE reads. A little over 800,000 bytes. |
httpd-4.5.1-samplib.xmit | The sample library: the procedure of the started task, a Parmlib member and the job that allocates the webroot disk. About 22,000 bytes. |
httpd-4.5.1-alloc.jcl | Allocates the two libraries that SMP installs into. Run it once. |
httpd-4.5.1-inst.jcl | The install job: TSO RECEIVE of both XMIT files, then SMP RECEIVE, APPLY and ACCEPT. |
httpd-webroot.img | The webroot disk: a 1 MB file system image with the welcome page. It is not part of the SMP installation (“The Document Root Disk”). |
Table 2. The files of the installation package
The load XMIT holds five load modules. Only the first is the server:
| Module | What it is |
HTTPD | The server. It is the only module that the started task names. |
HTTPDSRV | A display module for a browser. Route /.dsrv. |
HTTPDM | A display module for a terminal client. Route /.dm. |
HTTPDMTT | A display module for the master trace table. Route /.dmtt. |
ABEND0C1 | A module that abends on purpose, for testing. Route /.abend. |
Table 3. The load modules
Nothing uses the last four until a MOD= line in the Parmlib member names them, and the shipped member has those lines as comments. They are diagnostic tools and need an AUTH= on the route. “The Display Modules” in the HTTPD Reference describes them.
The sample library holds three members:
| Member | What it is |
HTTPD | The procedure of the started task (“The Procedure and the Parmlib Member”). |
HTTPPRM0 | A Parmlib member to copy and edit. |
HTTPWEBR | A job that allocates the data set for the webroot disk (“The Document Root Disk”). |
Table 4. The members of the sample library
The installation creates these data sets. Their names are the same in every release:
| Data set | Role |
HTTPD.LINKLIB | The load library. SMP owns it. The STEPLIB of the procedure names it, and it can be on the APF list. Allocated by the allocation job. |
HTTPD.AHTTPLOD | The distribution library: the copy that SMP keeps for the accepted level. Allocated by the allocation job. |
HTTPD.HTTPLOAD | The staging library. TSO RECEIVE creates it, SMP reads the modules from it, and the last step of the install job scratches it. |
HTTPD.SAMPLIB | The sample library. TSO RECEIVE creates it. It is a plain library that SMP does not own. |
HTTPD.WEBROOT.UFS | The webroot disk. The job HTTPWEBR allocates it. SMP does not own it, and no upgrade touches it. |
Table 5. The data sets of the installation
What You Need
- MVS 3.8j on Hercules, with SMP 4 in working order: the procedures
SMPRECandSMPAPPand theSYS1.SMP*data sets. They are there on TK4-, TK5 and MVS/CE as delivered. - RAKF, for the logins (“RAKF Is Required for Logins”). This one is not optional.
- UFSD, only if you want to serve static files (“UFSD Is Optional”).
- mvsMF, only if you want the REST API that the shipped Parmlib member routes to (“mvsMF Is Optional”).
- A user ID that may submit jobs, change the procedure library of the started tasks and change a PARMLIB.
- A way to send a file to the host in binary (“Sending the Two XMIT Files”).
- Disk space for the four data sets of SMP and TSO RECEIVE. The allocation job asks for 5 cylinders for each of the two libraries. The staging library is about the size of the load XMIT and goes away again at the end of the install job.
UFSD Is Optional
HTTPD serves static files from the file system of UFSD, and from nowhere else. The setting DOCROOT names a path in that file system. Without UFSD there is nothing to serve statically.
Nothing about the installation needs UFSD. The SYSMOD declares no prerequisite. A UFSD that cannot be reached at the start is a warning and not a failure:
HTTPD044W UNABLE TO INITIALIZE FILE SYSTEM
The server starts and listens, and every MOD= route works. Only the requests for static files fail. Beware of one thing: HTTPD001I still says READY - SERVING /www in this case. The message names the document root and does not say that the file system is there. If you want a server without static files, put UFS=0 in the Parmlib member. That skips the initialisation and the warning (“The HTTPPRM Keywords” in the HTTPD Reference).
If you want static files, UFSD must run before HTTPD, as a started task of its own. HTTPD 4.5.1 is built against UFSD 1.5.2, as 4.5.0 was. A UFSD older than 1.5.0 is untested. The UFSD User’s Guide installs UFSD.
mvsMF Is Optional
The shipped Parmlib member has four active routes, and all of them go to the server module MVSMF: /zosmf/info, /zosmf/services/authenticate, /zosmf/restconsoles/* and /zosmf/*.
HTTPD loads a server module by name with the LINK SVC. The module must be in the STEPLIB of the started task or in the link list. Install mvsMF from its own package, which has its own guide, and put its library there. If HTTPD does not find the module, a request for one of the four paths gets an error response, and the console shows
HTTPD908E EXTERNAL PROGRAM MVSMF ...
(the rest of the line says why). If you do not use mvsMF, comment out or delete the four lines. Then no request reaches a module.
RAKF Is Required for Logins
HTTPD has no user database. A login with a user ID and a password is verified by RAKF, and the access to a protected resource is checked against RAKF profiles under the identity of the user who is logged in (Chapter 6, “Authentication and Security”). The started task itself also needs a user ID in RAKF (“Defining the Users and Profiles in RAKF”). On a system without RAKF nobody can log in, and no setting turns that off.
RAKF 1.2.x needs valid tables, and loads them at the IPL. Check the tables before the IPL (“Defining the Users and Profiles in RAKF”). If RAKF 1.2.x has no valid user table, it accepts every user ID. HTTPD 4.5.1 and later notice this at the start, write HTTPD042W and refuse all logins (“A Security System That Accepts Any User ID”). Install HTTPD 4.5.1 or later where RAKF 1.2.x runs.
Authority
The load module HTTPD is linked with AC(1), and the server needs APF authorization, because without it the LINK SVC and the security calls are not available. SMP copies the module and does not bind it again, so the attribute stays. There are two ways to get the authorization.
Through the APF list. Add HTTPD.LINKLIB to SYS1.PARMLIB(IEAAPF00). Each line has the data set name and the volume serial, separated by a blank. The previous last line gets a trailing comma. MVS 3.8j reads the APF list at the IPL only, and there is no dynamic APF list on TK5, so the entry costs one IPL. The name of the library does not change in later releases, so it costs only that one. The start shows
HTTPD002I AUTHORIZED BY LIBRARY (MODULE KEY 0)
Through RAKF. RAKF supplies the SVC 244, and HTTPD calls it itself at the start to get authorized. You need RAKF anyway, so this needs no other setup. The start shows
HTTPD002I AUTHORIZED BY SVC (MODULE KEY 8)
The capture of “Starting HTTPD” is this second case.
An APF entry on MVS 3.8j names the data set and the volume. The entry does not only permit a volume, it dictates one. The allocation job says UNIT=SYSDA and no volume, so it puts the library wherever SYSDA picks, and the next section shows a second run that put both libraries on other volumes than the first. If the volume is not the one in the entry, you get a library that exists, holds the right module and is not authorized. Pin the volume on the LINKLIB statement of the allocation job:
//LINKLIB DD DSN=HTTPD.LINKLIB,DISP=(NEW,CATLG,DELETE), // UNIT=SYSDA,VOL=SER=your-apf-volume,
Nothing reports the mismatch, because HTTPD recovers from it: it falls back to the SVC and comes up authorized. The only place where the two ways can be told apart is HTTPD002I. So AUTHORIZED BY SVC on a system where you added an APF entry is not a decision of the site but a symptom.
If neither way gives the authorization, the start writes
HTTPD012E HTTPD UNABLE TO DYNAMICALLY OBTAIN APF AUTHORIZATION
The first word after the message number is the name of the program. There is no HTTPD002I, and the step ends with a return code that is not zero. “The Started Task and the Package” in the HTTPD Reference has the whole story of the authorization, also for the modules that run in the task.
Sending the Two XMIT Files
Goal: the two XMIT files exist as data sets on the MVS system. Both are sequential data sets with fixed blocks of 80 bytes (RECFM=FB, LRECL=80), and both must arrive in binary. A text transfer changes the bytes, and then TSO RECEIVE cannot read the file. The data set names are your choice. The captures use HERC01.HTTPD.LOAD.XMIT and HERC01.HTTPD.SAMP.XMIT.
By FTP. If FTPD or another FTP server runs on the system, switch to binary and send both files:
$ ftp -v -n mvs.example.org 2121
Connected to mvs.example.org.
220 MVS 3.8j FTPD Server
ftp> user HERC01
331 Send password please.
Password:
230 HERC01 is logged on. Working directory is "HERC01.".
Remote system type is MVS.
ftp> progress off
Progress bar off.
ftp> binary
200 Representation type is Image
ftp> put httpd-4.5.1-load.xmit 'HERC01.HTTPD.LOAD.XMIT'
local: httpd-4.5.1-load.xmit remote: 'HERC01.HTTPD.LOAD.XMIT'
229 Entering Extended Passive Mode (|||2122|)
125 Storing data set HERC01.HTTPD.LOAD.XMIT
250 Transfer completed successfully.
843520 bytes sent in 00:03 (230.03 KiB/s)
ftp> put httpd-4.5.1-samplib.xmit 'HERC01.HTTPD.SAMP.XMIT'
local: httpd-4.5.1-samplib.xmit remote: 'HERC01.HTTPD.SAMP.XMIT'
229 Entering Extended Passive Mode (|||2122|)
125 Storing data set HERC01.HTTPD.SAMP.XMIT
250 Transfer completed successfully.
22240 bytes sent in 00:00 (196.11 KiB/s)
ftp> ls HTTPD.LOAD.XMIT
229 Entering Extended Passive Mode (|||2122|)
150 Opening data connection for file list
Volume Unit Referred Ext Used Recfm Lrecl BlkSz Dsorg Dsname
TSO001 3390 2026/10/30 1 19 FB 80 3120 PS HTTPD.LOAD.XMIT
226 List completed successfully.
ftp> ls HTTPD.SAMP.XMIT
229 Entering Extended Passive Mode (|||2122|)
150 Opening data connection for file list
Volume Unit Referred Ext Used Recfm Lrecl BlkSz Dsorg Dsname
TSO001 3390 2026/10/30 1 1 FB 80 3120 PS HTTPD.SAMP.XMIT
226 List completed successfully.
ftp> quit
221 Quit command received. Goodbye.
Read the capture from the top. After binary the server answers Representation type is Image, which is the binary mode. Each put ends with 250 Transfer completed successfully. The byte count must equal the size of the file on your disk. The listing at the end shows the result on the host: FB, 80, a block size of 3120, and 19 tracks for the load XMIT. If the record format or the length is something else, the transfer was not binary.
By mvsMF and zowe. If mvsMF runs, the zowe CLI can upload a file to a data set in binary mode. If you upgrade, use FTP instead: mvsMF is the server that you have to stop.
By IND$FILE. A 3270 emulator with the IND$FILE transfer can send the file in binary, without line-end conversion. Allocate the data set first as FB with a record length of 80, so that the label has the right record format.
What can go wrong. A text transfer, or a data set with another record format. The RECEIVE step of the install job then fails. Send the file again in binary, into a data set that does not yet exist.
Stopping a Running HTTPD
Goal: nothing has HTTPD’s libraries open. Skip this task on a first installation.
The allocation job creates HTTPD.LINKLIB, which a running HTTPD has open through its STEPLIB. The install job writes into it. A job that cannot get the library waits. The console shows the wait, the stop and the end of the wait:
$HASP100 HTTPDALC ON INTRDR HTTPD ALLOC
$HASP373 HTTPDALC STARTED - INIT 1 - CLASS A - SYS TK5R
IEF861I FOLLOWING RESERVED DATA SET NAMES UNAVAILABLE TO HTTPDALC
IEF863I DSN=HTTPD.LINKLIB
*IEF099I JOB HTTPDALC WAITING FOR DATA SETS
P HTTPD
HTTPD098I HTTPD SHUTTING DOWN
HTTPD060I SHUTDOWN SOCKET THREAD TCB(9AD080) TASK(162FC8) STACKSIZE(32768)
HTTPD060I SHUTDOWN WORKER(174C48) TCB(9A09C8) TASK(198FC8) STACKSIZE(65536)
HTTPD060I SHUTDOWN WORKER(174CC8) TCB(9A0CF8) TASK(187FC8) STACKSIZE(65536)
HTTPD060I SHUTDOWN WORKER(0ED7B0) TCB(9AD828) TASK(176FC8) STACKSIZE(65536)
HTTPD416I STATS: 0 REQUESTS, 0 ERRORS, 0 BYTES
HTTPD099I HTTPD SHUTDOWN COMPLETE
IEF404I HTTPD - ENDED - TIME=23.41.09
$HASP395 HTTPD ENDED
IEF403I HTTPDALC - STARTED - TIME=23.41.09
$HASP150 HTTPD ON PRINTER2 155 LINES
$HASP160 PRINTER2 INACTIVE - CLASS=Z
$HASP250 HTTPD IS PURGED
IEF404I HTTPDALC - ENDED - TIME=23.41.09
$HASP395 HTTPDALC ENDED
$HASP309 INIT 1 INACTIVE ******** C=A
IKJ144I UNDEFINED USERID(S)DUMMY
The first lines are the wait: IEF861I and IEF863I name the data set that the job cannot get, and IEF099I says the job waits. Stop HTTPD with P HTTPD. The job goes on as soon as the task has ended.
The stop is a normal MVS stop. The message HTTPD098I starts it, the threads end one by one (HTTPD060I), and HTTPD416I prints the counters of the run. HTTPD099I says that the shutdown is complete, and $HASP395 HTTPD ENDED is the line that tells you the address space is gone. Wait for it before you go on. There is no F HTTPD,SHUTDOWN, although the comments in the procedure still list it (“Console Commands” in the HTTPD Reference).
The capture is of a second run of the allocation job on a system that already had the libraries. It ends with a good-looking return code, and the next section explains why that is not good.
Allocating the Product Data Sets
Goal: the two libraries that SMP installs into exist and are cataloged. Run the allocation job httpd-4.5.1-alloc.jcl once, on a system that has no HTTPD yet. It allocates a program library with undefined records (RECFM=U, BLKSIZE=15040) for each of HTTPD.LINKLIB and HTTPD.AHTTPLOD. Each has 5 cylinders as primary space, 2 as secondary and 20 directory blocks. These two libraries are the data sets of this chapter that SMP owns.
The job has no DELETE step on purpose. After the SYSMOD is accepted, the distribution library holds the accepted copy of every module. A rerun that scratched it would leave the SMP records saying “accepted” with an empty library behind them, and nothing would tell you. The comment in the job gives the rule: if you must start over, cut the FMID out with UCLIN (Chapter 11, “Removing HTTPD”), and then delete the data sets by hand. An accepted function cannot be rejected or restored.
Edit UNIT and VOL=SER if SYSDA is not what you want. Pin the volume if you use the APF list (“Authority”). Submit the job. The console shows that the job started and that it ended:
$HASP100 HTTPDALC ON INTRDR HTTPD ALLOC
$HASP373 HTTPDALC STARTED - INIT 1 - CLASS A - SYS TK5R
IEF403I HTTPDALC - STARTED - TIME=23.35.45
IEF404I HTTPDALC - ENDED - TIME=23.35.45
$HASP395 HTTPDALC ENDED
$HASP309 INIT 1 INACTIVE ******** C=A
IKJ144I UNDEFINED USERID(S)DUMMY
The last line, IKJ144I, comes from the job card, which has NOTIFY=DUMMY. The user DUMMY does not exist. The message does not change the result of the job. The step and its return code are in the job log:
J E S 2 J O B L O G
23.35.45 JOB nn $HASP373 HTTPDALC STARTED - INIT 1 - CLASS A - SYS TK5R
23.35.45 JOB nn IEF403I HTTPDALC - STARTED - TIME=23.35.45
23.35.45 JOB nn IEFACTRT - Stepname Procstep Program Retcode
23.35.45 JOB nn HTTPDALC ALLOC IEFBR14 RC= 0000
23.35.45 JOB nn IEF404I HTTPDALC - ENDED - TIME=23.35.45
23.35.45 JOB nn $HASP395 HTTPDALC ENDED
The step is IEFBR14 and the return code is 0000. The system messages of the job say where the data sets went:
IEF236I ALLOC. FOR HTTPDALC ALLOC
IEF237I 192 ALLOCATED TO LINKLIB
IEF237I 298 ALLOCATED TO SYS00001
IEF237I 191 ALLOCATED TO AHTTPLOD
IEF142I HTTPDALC ALLOC - STEP WAS EXECUTED - COND CODE 0000
IEF285I HTTPD.LINKLIB CATALOGED *--------0
IEF285I VOL SER NOS= TSO003.
IEF285I SYS1.UCAT.TK5 KEPT *--------0
IEF285I VOL SER NOS= TK5001.
IEF285I HTTPD.AHTTPLOD CATALOGED *--------0
IEF285I VOL SER NOS= TSO002.
IEF373I STEP /ALLOC / START 26303.2335
IEF374I STEP /ALLOC / STOP 26303.2335 CPU 0MIN 00.00SEC SRB 0MIN 00.00SEC VIRT 4K SYS 172K
IEF375I JOB /HTTPDALC/ START 26303.2335
IEF376I JOB /HTTPDALC/ STOP 26303.2335 CPU 0MIN 00.00SEC SRB 0MIN 00.00SEC
Read IEF285I. Both data sets are CATALOGED, and VOL SER NOS= names the volumes. Write down the volume of HTTPD.LINKLIB if you use the APF list.
What can go wrong: the data set exists. Run the job on a system that has the names already, and it also ends with condition code 0000. The system messages show the difference:
IEF236I ALLOC. FOR HTTPDALC ALLOC
IEF237I 191 ALLOCATED TO LINKLIB
IEF237I 298 ALLOCATED TO SYS00008
IEF237I 192 ALLOCATED TO AHTTPLOD
IEF142I HTTPDALC ALLOC - STEP WAS EXECUTED - COND CODE 0000
IEF287I HTTPD.LINKLIB NOT CATLGD 2 *--------0
IEF287I VOL SER NOS= TSO002.
IEF285I SYS1.UCAT.TK5 KEPT *--------0
IEF285I VOL SER NOS= TK5001.
IEF287I HTTPD.AHTTPLOD NOT CATLGD 2 *--------0
IEF287I VOL SER NOS= TSO003.
IEF373I STEP /ALLOC / START 26303.2340
IEF374I STEP /ALLOC / STOP 26303.2341 CPU 0MIN 00.00SEC SRB 0MIN 00.00SEC VIRT 4K SYS 172K
IEF375I JOB /HTTPDALC/ START 26303.2340
IEF376I JOB /HTTPDALC/ STOP 26303.2341 CPU 0MIN 00.00SEC SRB 0MIN 00.00SEC
IEF287I with NOT CATLGD 2 says that the new data set was created and could not be cataloged, because the name is taken. Note the volumes: the new copies are on the other volumes than in the first run. They are not the libraries that the system uses. A return code of 0000 says that the job ran. It does not say that the work happened. Look at IEF285I and IEF287I every time, and delete the uncataloged copies by hand.
What can go wrong: a running HTTPD. The job waits (“Stopping a Running HTTPD”).
What can go wrong: SB37. The space is in cylinders on purpose. A primary in tracks reaches the 16-extent limit long before the volume is full, and the abend that follows reads like a full volume.
Editing and Submitting the Install Job
Goal: the install job runs with the names of your two XMIT data sets. Open httpd-4.5.1-inst.jcl. The only lines that you have to change are the two RECEIVE statements, in the steps RECV1 and RECV2. They name the data sets that you sent. The capture is the difference between the shipped job and the edited one:
$ diff httpd-4.5.1-inst.jcl.orig httpd-4.5.1-inst.jcl
57c57
< RECEIVE INDSN('CHANGE.ME.HTTPLOAD') -
---
> RECEIVE INDSN('HERC01.HTTPD.LOAD.XMIT') -
66c66
< RECEIVE INDSN('CHANGE.ME.SAMPLIB') -
---
> RECEIVE INDSN('HERC01.HTTPD.SAMP.XMIT') -
Keep the rest. The job has eight steps:
| Step | What it does |
DELOLD | Deletes HTTPD.HTTPLOAD and HTTPD.SAMPLIB, the two targets of the next steps. TSO RECEIVE refuses to merge into an existing data set, and without this step the job would run only once. |
RECV1 | TSO RECEIVE of the load XMIT into HTTPD.HTTPLOAD. |
RECV2 | TSO RECEIVE of the sample XMIT into HTTPD.SAMPLIB. |
RECV | SMP RECEIVE. The SYSMOD travels inside the job and goes into the SMP inventory. |
APPLYCHK | SMP APPLY with CHECK: a dry run that changes nothing. |
APPLY | SMP APPLY: copies the five modules into HTTPD.LINKLIB. |
ACCEPT | SMP ACCEPT: copies them into HTTPD.AHTTPLOD and makes this level the one a RESTORE would return to. |
CLEANUP | Scratches the staging library HTTPD.HTTPLOAD. |
Table 6. The steps of the install job
The steps depend on each other through condition codes. The step RECV runs if RECV2 ended with 0. APPLYCHK runs if RECV ended with 0, and APPLY runs if APPLYCHK ended with 0. So the apply does not start when the dry run found a problem. ACCEPT runs if APPLY ended with 4 or lower, and CLEANUP only if ACCEPT ended with 0.
The SYSMOD is part of the job as an inline data set, in a DD DATA,DLM=@@ statement. It is plain text, so there is no third file to send and no third data set to allocate. The terminator is @@ and not the usual /*, because the SYSMOD contains statements that start with // and a copy statement that ends with /*.
The steps APPLYCHK, APPLY and ACCEPT carry a note in the job: the DDs that override one of the procedure SMPAPP must come before the DDs that the step adds. In the wrong order, SMP quietly uses the data set of the procedure, and the messages still name the one you wanted. Do not reorder those statements.
Submit the job. From a workstation, FTP can do it with the file type JES:
$ ftp -v -n mvs.example.org 2121
Connected to mvs.example.org.
220 MVS 3.8j FTPD Server
ftp> user HERC01
331 Send password please.
Password:
230 HERC01 is logged on. Working directory is "HERC01.".
Remote system type is MVS.
ftp> progress off
Progress bar off.
ftp> quote site filetype=jes
200 SITE command was accepted
ftp> put httpd-4.5.1-inst.jcl httpd-4.5.1-inst.jcl
local: httpd-4.5.1-inst.jcl remote: httpd-4.5.1-inst.jcl
229 Entering Extended Passive Mode (|||2122|)
125 Sending Job to JES internal reader FIXrecfm 80
250-It is known to JES as JOBnnnnn
250 Transfer completed successfully.
5914 bytes sent in 00:00 (80.83 KiB/s)
ftp> quit
221 Quit command received. Goodbye.
The command quote site filetype=jes switches the FTP server to job submission. The put then sends the file to the internal reader of JES, and the line 250-It is known to JES as JOBnnnnn names the job. You can also submit the job from TSO, from the mvsMF job API or from a card reader. Under a minute later the job is done.
Reading the Result
Goal: know whether the install job did its work. The console shows that the job started and that it ended. It does not show the steps:
$HASP100 HTTPDINS ON INTRDR HTTPD INSTALL
$HASP373 HTTPDINS STARTED - INIT 1 - CLASS A - SYS TK5R
IEF403I HTTPDINS - STARTED - TIME=23.36.30
IEF404I HTTPDINS - ENDED - TIME=23.37.19
$HASP395 HTTPDINS ENDED
$HASP309 INIT 1 INACTIVE ******** C=A
IKJ144I UNDEFINED USERID(S)DUMMY
The step table is in the job log, with the time of each step. Every step ends with RC= 0000:
J E S 2 J O B L O G
23.36.30 JOB nn $HASP373 HTTPDINS STARTED - INIT 1 - CLASS A - SYS TK5R
23.36.30 JOB nn IEF403I HTTPDINS - STARTED - TIME=23.36.30
23.36.30 JOB nn IEFACTRT - Stepname Procstep Program Retcode
23.36.30 JOB nn HTTPDINS DELOLD IDCAMS RC= 0000
23.36.31 JOB nn HTTPDINS RECV1 IKJEFT01 RC= 0000
23.36.32 JOB nn HTTPDINS RECV2 IKJEFT01 RC= 0000
23.36.32 JOB nn HTTPDINS RECV HMASMP HMASMP RC= 0000
23.36.42 JOB nn HTTPDINS APPLYCHK HMASMP HMASMP RC= 0000
23.37.03 JOB nn HTTPDINS APPLY HMASMP HMASMP RC= 0000
23.37.19 JOB nn HTTPDINS ACCEPT HMASMP HMASMP RC= 0000
23.37.19 JOB nn HTTPDINS CLEANUP IDCAMS RC= 0000
23.37.19 JOB nn IEF404I HTTPDINS - ENDED - TIME=23.37.19
23.37.19 JOB nn $HASP395 HTTPDINS ENDED
The return codes mean this:
- 0000. The step did what it says.
- 0004. A warning. It is normal in one place: the
APPLYstep of an upgrade ends with 0004 (Chapter 10, “Upgrading HTTPD”). A first installation ends with 0000 in every step. - 0008 or higher. The step failed. The conditions stop the later steps, so the first step with a high code is the one to read.
The messages of every step are in the job output. The steps in order:
DELOLD. The step ends with 0000, although the capture looks like a failure:
IDCAMS SYSTEM SERVICES TIME: 23:36:30 10/30/26 PAGE 1
DELETE HTTPD.HTTPLOAD NONVSAM SCRATCH PURGE
IKJ56228I DATA SET HTTPD.HTTPLOAD NOT IN CATALOG OR CATALOG CAN NOT BE
IKJ56228I ACCESSED
IDC0551I **ENTRY HTTPD.HTTPLOAD NOT DELETED
IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 8
DELETE HTTPD.SAMPLIB NONVSAM SCRATCH PURGE
IDC0550I ENTRY (A) HTTPD.SAMPLIB DELETED
IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 0
SET MAXCC=0
IDC0002I IDCAMS PROCESSING COMPLETE. MAXIMUM CONDITION CODE WAS 0
The first delete says NOT DELETED and ends with condition code 8, because HTTPD.HTTPLOAD does not exist yet. The statement SET MAXCC=0 then makes the step end with 0. This is normal and not an error. The second delete found an old HTTPD.SAMPLIB on the system of the capture and deleted it (IDC0550I). Members that you edited in an old sample library are gone with it.
RECV1 and RECV2. TSO RECEIVE unpacks an XMIT file into a data set:
RECEIVE INDSN('HERC01.HTTPD.LOAD.XMIT') DATASET('HTTPD.HTTPLOAD')
NJE38 RECEIVE v2.5.0
Receiving 'HTTPD.V4R5M1.LINKLIB' from ORIGNODE(IBMUSER)
Receive into 'HTTPD.HTTPLOAD' successful
END
The line Receive into 'HTTPD.HTTPLOAD' successful is the one to find. The name after Receiving is the name the XMIT had on the machine where it was made, and it is not the name of your data set. The sample library has the same shape:
RECEIVE INDSN('HERC01.HTTPD.SAMP.XMIT') DATASET('HTTPD.SAMPLIB')
NJE38 RECEIVE v2.5.0
Receiving 'HTTPD.SAMPLIB' from ORIGNODE(HTTPD)
Receive into 'HTTPD.SAMPLIB' successful
END
RECV. SMP reads the SYSMOD from the inline data set and stores it. The output repeats the statements and ends with a return code. In it you see the function THTP451, the statement ++VER(Z038) DELETE(THTP450), and one ++MOD statement for each of the five modules.
DATE 26.303 TIME 23:36:32 HMASMP LVL 04.48 MESSAGES AND CONTROL STATEMENTS PAGE 0001
HMA4240 HMASMP EXEC PARM = 'DATE=U'
RESETRC .
HMA2050 RESETRC PROCESSING COMPLETED - HIGHEST RETURN CODE IS 00
RECEIVE SELECT(THTP451) .
----------++FUNCTION(THTP451) .
----------++VER(Z038) DELETE(THTP450)
---------- /* httpd 4.5.1 */
---------- /* Load modules are copied from the LKLIB, not re-bound. */ .
----------++JCLIN .
----------++MOD(ABEND0C1) LKLIB(HTTPLOAD) DISTLIB(AHTTPLOD) .
----------++MOD(HTTPD) LKLIB(HTTPLOAD) DISTLIB(AHTTPLOD) .
----------++MOD(HTTPDM) LKLIB(HTTPLOAD) DISTLIB(AHTTPLOD) .
----------++MOD(HTTPDMTT) LKLIB(HTTPLOAD) DISTLIB(AHTTPLOD) .
----------++MOD(HTTPDSRV) LKLIB(HTTPLOAD) DISTLIB(AHTTPLOD) .
HMA3930 SYSMOD THTP451 SUCCESSFULLY RECEIVED
DATE 26.303 TIME 23:36:32 HMASMP LVL 04.48 MESSAGES AND CONTROL STATEMENTS PAGE 0002
RECEIVE SUMMARY REPORT
SYSMOD STATUS TYPE ------------------------
THTP451 RECEIVED FUNCTION
DATE 26.303 TIME 23:36:32 HMASMP LVL 04.48 MESSAGES AND CONTROL STATEMENTS PAGE 0003
HMA2050 RECEIVE PROCESSING COMPLETED - HIGHEST RETURN CODE IS 00
HMA2050 HMASMP PROCESSING COMPLETED - HIGHEST RETURN CODE IS 00
APPLYCHK. The dry run. Its output has the same reports as the real run and changes nothing.
APPLY. The real work. Look for the five HMA2380 lines:
DATE 26.303 TIME 23:36:42 HMASMP LVL 04.48 MESSAGES AND CONTROL STATEMENTS PAGE 0001
HMA4240 HMASMP EXEC PARM = 'DATE=U'
APPLY S(THTP451) DIS(WRITE) .
HMA4140 SMPCDS DIRECTORY SUCCESSFULLY LOADED FOR IN-STORAGE UPDATE OPERATIONS
HMA4180 INLINE JCLIN PROCESSING SUCCESSFUL FOR SYSMOD=THTP451
HMA2380 COPY SUCCESSFUL - MOD=ABEND0C1 - LMOD=ABEND0C1 - LIBRARY=LINKLIB - SYSMOD=THTP451 - RETURN CODE=00
HMA2380 COPY SUCCESSFUL - MOD=HTTPD - LMOD=HTTPD - LIBRARY=LINKLIB - SYSMOD=THTP451 - RETURN CODE=00
HMA2380 COPY SUCCESSFUL - MOD=HTTPDM - LMOD=HTTPDM - LIBRARY=LINKLIB - SYSMOD=THTP451 - RETURN CODE=00
HMA2380 COPY SUCCESSFUL - MOD=HTTPDMTT - LMOD=HTTPDMTT - LIBRARY=LINKLIB - SYSMOD=THTP451 - RETURN CODE=00
HMA2380 COPY SUCCESSFUL - MOD=HTTPDSRV - LMOD=HTTPDSRV - LIBRARY=LINKLIB - SYSMOD=THTP451 - RETURN CODE=00
HMA2270 APPLY PROCESSING SUCCESSFULLY COMPLETED FOR SYSMOD THTP451
HMA3680 SMPCDS IN STORAGE DIRECTORY SUCCESSFULLY REWRITTEN
HMA2050 APPLY PROCESSING COMPLETED - HIGHEST RETURN CODE IS 00
DATE 26.303 TIME 23:37:03 HMASMP LVL 04.48 MESSAGES AND CONTROL STATEMENTS PAGE 0002
SYSMOD STATUS REPORT FOR APPLY PROCESSING
NOTE: '-' INDICATES THE REQUISITE SYSMOD CONDITION IS NOT SATISFIED
'*' INDICATES THE NON SATISFIED REQUISITE SYSMOD CONDITION IS BYPASSED
SYSMOD STATUS TYPE FMID REQUISITE AND SUPEDBY SYSMODS
THTP450 DELETED FUNCTION
THTP451 APPLIED FUNCTION THTP451
DATE 26.303 TIME 23:37:03 HMASMP LVL 04.48 MESSAGES AND CONTROL STATEMENTS PAGE 0003
ELEMENT SUMMARY REPORT FOR APPLY PROCESSING
ELEM ELEMENT ELEM CURRENT CURRENT MAC/SRC DISTSRC ASSEM LOAD MOD ---LMOD SYSLIB--- SYSMOD SYSMOD
TYPE NAME STATUS FMID RMID SYSLIB LIBRARY NAMES NAME STATUS
MOD ABEND0C1 APPLIED THTP451 THTP451 ABEND0C1 LINKLIB THTP451 APPLIED
MOD HTTPD APPLIED THTP451 THTP451 HTTPD LINKLIB THTP451 APPLIED
MOD HTTPDM APPLIED THTP451 THTP451 HTTPDM LINKLIB THTP451 APPLIED
MOD HTTPDMTT APPLIED THTP451 THTP451 HTTPDMTT LINKLIB THTP451 APPLIED
MOD HTTPDSRV APPLIED THTP451 THTP451 HTTPDSRV LINKLIB THTP451 APPLIED
DATE 26.303 TIME 23:37:03 HMASMP LVL 04.48 MESSAGES AND CONTROL STATEMENTS PAGE 0004
DELETED FUNCTION REPORT FOR APPLY PROCESSING
SYSMOD DELETED THE
CAUSING THE FOLLOWING SYSMODS
DELETION TYPE SYSMOD
NO SYSMODS DELETED
DATE 26.303 TIME 23:37:03 HMASMP LVL 04.48 MESSAGES AND CONTROL STATEMENTS PAGE 0005
HMA2050 HMASMP PROCESSING COMPLETED - HIGHEST RETURN CODE IS 00
Each HMA2380 COPY SUCCESSFUL line names a module, the library LINKLIB and the SYSMOD, and ends with RETURN CODE=00. The five lines are the proof that five modules were copied. The final line HMA2050 ... HIGHEST RETURN CODE IS 00 is only a summary. The copy is done by IEBCOPY, which SMP starts. Its output lists the same members and says how many tracks and directory blocks of the library are still unused:
IEBCOPY MESSAGES AND CONTROL STATEMENTS PAGE 0001
COPY OUTDD=LINKLIB,INDD=HTTPLOAD
SELECT MEMBER=((ABEND0C1,,R)) THTP451
SELECT MEMBER=((HTTPD,,R)) THTP451
SELECT MEMBER=((HTTPDM,,R)) THTP451
SELECT MEMBER=((HTTPDMTT,,R)) THTP451
SELECT MEMBER=((HTTPDSRV,,R)) THTP451
IEB167I FOLLOWING MEMBER(S) COPIED FROM INPUT DATA SET REFERENCED BY HTTPLOAD -
IEB154I ABEND0C1 HAS BEEN SUCCESSFULLY COPIED
IEB154I HTTPD HAS BEEN SUCCESSFULLY COPIED
IEB154I HTTPDM HAS BEEN SUCCESSFULLY COPIED
IEB154I HTTPDMTT HAS BEEN SUCCESSFULLY COPIED
IEB154I HTTPDSRV HAS BEEN SUCCESSFULLY COPIED
IEB144I THERE ARE 0000052 UNUSED TRACKS IN OUTPUT DATA SET REFERENCED BY LINKLIB
IEB149I THERE ARE 0000019 UNUSED DIRECTORY BLOCKS IN OUTPUT DIRECTORY
IEB147I END OF JOB -00 WAS HIGHEST SEVERITY CODE
ACCEPT. The same copy, into the distribution library HTTPD.AHTTPLOD. The output has five HMA2380 lines with LIBRARY=AHTTPLOD, and it ends with HMA2270 ACCEPT PROCESSING:
SUCCESSFULLY COMPLETED
DATE 26.303 TIME 23:37:04 HMASMP LVL 04.48 MESSAGES AND CONTROL STATEMENTS PAGE 0001
HMA4240 HMASMP EXEC PARM = 'DATE=U'
ACCEPT S(THTP451) DIS(WRITE) .
HMA4140 SMPACDS DIRECTORY SUCCESSFULLY LOADED FOR IN-STORAGE UPDATE OPERATIONS
HMA2380 COPY SUCCESSFUL - MOD=ABEND0C1 - LMOD=ABEND0C1 - LIBRARY=AHTTPLOD - SYSMOD=THTP451 - RETURN CODE=00
HMA2380 COPY SUCCESSFUL - MOD=HTTPD - LMOD=HTTPD - LIBRARY=AHTTPLOD - SYSMOD=THTP451 - RETURN CODE=00
HMA2380 COPY SUCCESSFUL - MOD=HTTPDM - LMOD=HTTPDM - LIBRARY=AHTTPLOD - SYSMOD=THTP451 - RETURN CODE=00
HMA2380 COPY SUCCESSFUL - MOD=HTTPDMTT - LMOD=HTTPDMTT - LIBRARY=AHTTPLOD - SYSMOD=THTP451 - RETURN CODE=00
HMA2380 COPY SUCCESSFUL - MOD=HTTPDSRV - LMOD=HTTPDSRV - LIBRARY=AHTTPLOD - SYSMOD=THTP451 - RETURN CODE=00
HMA2270 ACCEPT PROCESSING SUCCESSFULLY COMPLETED FOR SYSMOD THTP451
HMA3680 SMPACDS IN STORAGE DIRECTORY SUCCESSFULLY REWRITTEN
HMA2050 ACCEPT PROCESSING COMPLETED - HIGHEST RETURN CODE IS 00
DATE 26.303 TIME 23:37:19 HMASMP LVL 04.48 MESSAGES AND CONTROL STATEMENTS PAGE 0002
SYSMOD STATUS REPORT FOR ACCEPT PROCESSING
NOTE: '-' INDICATES THE REQUISITE SYSMOD CONDITION IS NOT SATISFIED
'*' INDICATES THE NON SATISFIED REQUISITE SYSMOD CONDITION IS BYPASSED
SYSMOD STATUS TYPE FMID REQUISITE AND SUPEDBY SYSMODS
THTP450 DELETED FUNCTION
THTP451 ACCEPTED FUNCTION THTP451
DATE 26.303 TIME 23:37:19 HMASMP LVL 04.48 MESSAGES AND CONTROL STATEMENTS PAGE 0003
ELEMENT SUMMARY REPORT FOR ACCEPT PROCESSING
ELEM ELEMENT ELEM CURRENT CURRENT MAC/SRC DISTSRC ASSEM LOAD MOD ---MOD DISTLIB--- SYSMOD SYSMOD
TYPE NAME STATUS FMID RMID DISTLIB LIBRARY NAMES NAME STATUS
MOD ABEND0C1 ACCEPTED THTP451 THTP451 AHTTPLOD THTP451 ACCEPTED
MOD HTTPD ACCEPTED THTP451 THTP451 AHTTPLOD THTP451 ACCEPTED
MOD HTTPDM ACCEPTED THTP451 THTP451 AHTTPLOD THTP451 ACCEPTED
MOD HTTPDMTT ACCEPTED THTP451 THTP451 AHTTPLOD THTP451 ACCEPTED
MOD HTTPDSRV ACCEPTED THTP451 THTP451 AHTTPLOD THTP451 ACCEPTED
DATE 26.303 TIME 23:37:19 HMASMP LVL 04.48 MESSAGES AND CONTROL STATEMENTS PAGE 0004
DELETED FUNCTION REPORT FOR ACCEPT PROCESSING
SYSMOD DELETED THE
CAUSING THE FOLLOWING SYSMODS
DELETION TYPE SYSMOD
NO SYSMODS DELETED
DATE 26.303 TIME 23:37:19 HMASMP LVL 04.48 MESSAGES AND CONTROL STATEMENTS PAGE 0005
HMA2050 HMASMP PROCESSING COMPLETED - HIGHEST RETURN CODE IS 00
CLEANUP. The staging library goes away:
IDCAMS SYSTEM SERVICES TIME: 23:37:19 10/30/26 PAGE 1
DELETE HTTPD.HTTPLOAD NONVSAM SCRATCH PURGE
IDC0550I ENTRY (A) HTTPD.HTTPLOAD DELETED
IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 0
IDC0002I IDCAMS PROCESSING COMPLETE. MAXIMUM CONDITION CODE WAS 0
The system of these captures had never had THTP450. The reports say THTP450 DELETED all the same: SMP lists the FMID that the statement ++VER DELETE names, whether or not the system holds it. When the install is done, both zones of SMP hold THTP450 as a mark with the line DELBY = THTP451 (“Verifying the Install”). The return codes are the same as on a system that had it.
Verifying the Install
Goal: prove that the modules are in the library and that SMP knows them. A return code says that the job ran. It does not say that the work happened.
The members of the library. List the directory of HTTPD.LINKLIB. In TSO, LISTDS 'HTTPD.LINKLIB' MEMBERS does it. The utility IEHLIST prints more. Its output for the library of the capture:
SYSTEMS SUPPORT UTILITIES---IEHLIST PAGE 1
DIRECTORY INFO FOR SPECIFIED PDS ON VOL TSO003
HTTPD.LINKLIB
MEMBERS TTRC VARIABLE USER DATA ---(USER DATA AND TTRC ARE IN HEX)
ABEND0C1 0000162C 0001010000 000000C2C2 0152583060 0027B08800 00010000
HTTPD 00030F2C 0004110000 000000C2C2 047E480558 012FD88800 00010100
HTTPDM 000C0B2C 000C250000 000000C2C2 016DD830C8 003BF88800 00010000
HTTPDMTT 000F0A2C 000F250000 000000C2C2 01669833A0 002D888800 00010000
HTTPDSRV 0012072C 0012290000 000000C2C2 02442009F8 00BA888800 00010000
OF THE 00020 DIRECTORY BLOCKS ALLOCATED TO THIS PDS, 00019 ARE(IS) COMPLETELY UNUSED
There must be five members: ABEND0C1, HTTPD, HTTPDM, HTTPDMTT and HTTPDSRV. The last line says that 19 of the 20 directory blocks are completely unused. The first line names the volume where the library is.
The SMP record. Ask SMP for the SYSMOD and for one load module. The job is the procedure SMPAPP with these control statements:
//LISTCDS EXEC SMPAPP //SMPCNTL DD * RESETRC . LIST CDS SYSMOD(THTP451) . LIST CDS LMOD(HTTPD) . /*
The output:
DATE 26.303 TIME 23:37:53 HMASMP LVL 04.48 MESSAGES AND CONTROL STATEMENTS PAGE 0001
HMA4240 HMASMP EXEC PARM = 'DATE=U'
RESETRC .
HMA2050 RESETRC PROCESSING COMPLETED - HIGHEST RETURN CODE IS 00
LIST CDS SYSMOD(THTP451) .
DATE 26.303 TIME 23:37:53 HMASMP LVL 04.48 MESSAGES AND CONTROL STATEMENTS PAGE 0002
SMPCDS SYSMOD ENTRIES
NAME
THTP451 TYPE = FUNCTION
STATUS = REC APP ACC
FMID = THTP451
JCLIN = YES
DATE/TIME REC = 26.303 23:36:32
APP = 26.303 23:36:58
ACC = 26.303 23:37:14
DELETE VER(001) = THTP450
MOD = ABEND0C1 HTTPD HTTPDM HTTPDMTT HTTPDSRV
DATE 26.303 TIME 23:37:53 HMASMP LVL 04.48 MESSAGES AND CONTROL STATEMENTS PAGE 0003
HMA2050 LIST PROCESSING COMPLETED - HIGHEST RETURN CODE IS 00
LIST CDS LMOD(HTTPD) .
DATE 26.303 TIME 23:37:53 HMASMP LVL 04.48 MESSAGES AND CONTROL STATEMENTS PAGE 0004
SMPCDS LOAD MODULE ENTRIES
NAME
HTTPD LASTUPD = THTP451 TYPE=ADD
SYSTEM LIBRARY = LINKLIB
LKED ATTRIBUTES = COPY
DATE 26.303 TIME 23:37:53 HMASMP LVL 04.48 MESSAGES AND CONTROL STATEMENTS PAGE 0005
HMA2050 LIST PROCESSING COMPLETED - HIGHEST RETURN CODE IS 00
HMA2050 HMASMP PROCESSING COMPLETED - HIGHEST RETURN CODE IS 00
Read the capture for four facts. The status is REC APP ACC: the SYSMOD is received, applied and accepted. The line DELETE VER(001) names the predecessor that the SYSMOD replaces. The line MOD = lists the five modules. And LASTUPD = THTP451 for the load module HTTPD, with SYSTEM LIBRARY = LINKLIB, says that the module in the load library comes from this level.
If the member list is short, or the status lacks ACC, the install did not do its work, whatever the return codes said.
The predecessor. The SYSMOD names THTP450 as the FMID it deletes, so SMP keeps a mark for it, also on a system that never had it. A list of SYSMOD(THTP450) shows the type FUNCTION and the line DELBY = THTP451, with no status and no modules. Ask for it in the CDS with LIST CDS SYSMOD(THTP450) and in the ACDS with LIST ACDS SYSMOD(THTP450): both zones have the mark. The mark is not a sign of an old release on the system.
The Procedure and the Parmlib Member
Goal: the procedure HTTPD is in a procedure library of the started tasks, and a Parmlib member exists for it. The sample library has both. Copy the procedure with IEBGENER:
//COPY EXEC PGM=IEBGENER //SYSPRINT DD SYSOUT=* //SYSUT1 DD DISP=SHR,DSN=HTTPD.SAMPLIB(HTTPD) //SYSUT2 DD DISP=SHR,DSN=SYS2.PROCLIB(HTTPD) //SYSIN DD DUMMY
SYS2.PROCLIB is an example. Use the procedure library of the started tasks on your system. Copy HTTPPRM0 the same way into the Parmlib. In the shipped member all keywords are comments, except the four mvsMF routes of “mvsMF Is Optional”. Edit it for your system (“The HTTPPRM Keywords” in the HTTPD Reference describes every keyword, and Chapter 4, “Configuring HTTPD” the way to choose them).
The procedure starts with four symbolics:
//HTTPD PROC M=HTTPPRM0, // D='SYS2.PARMLIB', // STCUSER=HTTPD, // STCGRP=USER
M- The member of the Parmlib. The default is
HTTPPRM0. Start with another member byS HTTPD,M=HTTPPRM1. D- The data set of the Parmlib. The default is
SYS2.PARMLIB. Check that the data set named by D exists on your system. If you use another one, change the default in the procedure, or name the data set on every start withS HTTPD,D='...'. STCUSER- The user ID that the server logs on as at the start (“Defining the Users and Profiles in RAKF”).
STCGRP- The group of that user. The name of the symbolic is
STCGRP, but the keyword in the PARM isSTCGROUP: a symbolic parameter name is at most 7 characters long.
The program statement is
//HTTPD EXEC PGM=HTTPD,REGION=8M,TIME=1440, // PARM='STCUSER=&STCUSER STCGROUP=&STCGRP'
The REGION=8M is the stock value. A server that is to run many REXX or Lua requests at the same time needs more, and MAXTASK must not be raised without it: “The Started Task and the Package” in the HTTPD Reference gives the sizes, and “Troubleshooting” the symptom.
The PARM is separated by blanks, not by commas. A CONFIG= in the PARM is a leftover of an old release. It gives HTTPD024W and HTTPD024I, and the server takes its configuration from the DD HTTPPRM as usual.
The data definitions. The procedure ships with these DD statements:
| DD | Purpose |
STEPLIB | HTTPD.LINKLIB. The load library of the server and of its modules. The package build writes the name into the procedure. |
SYSUDUMP, SNAP | Dump output. |
HTTPDERR, HTTPDOUT, HTTPDBG, HTTPSTAT | Output of the server, to the spool. |
HTTPDIN | Dummy. |
HTTPPRM | The Parmlib member: DSN=&D(&M), DISP=SHR, FREE=CLOSE. |
HASPCKPT, HASPACE1 | Comment lines. The JES2 checkpoint and the spool. Optional: see below. |
Table 7. The DD statements of the procedure
Do not add the DDs SYSPRINT, SYSTERM and SYSIN. The server refuses to start with them: HTTPD014E, HTTPD015E and HTTPD016E name them. The messages HTTPD017W, HTTPD018W and HTTPD019W report that HTTPDOUT, HTTPDERR or HTTPDIN is missing, and they also stop the start. “Messages” in the HTTPD Reference lists them.
HASPCKPT and HASPACE1. HTTPD itself never opens them. They are for the server modules. A module runs in the task of HTTPD and has no allocations of its own, and the jobs API of mvsMF reads the JES2 checkpoint and spool in that task. The shipped procedure has both statements as comment lines, and you need them in two cases only:
- You run mvsMF 1.3.0 or earlier. It opens the two data sets by their DD names. Without the statements, a job list answers 500, and a request for one job by name and id answers 404 “job not found”, a spool read included, although the job exists. The console shows
MVSMF201E UNABLE TO OPEN THE JES2 CHECKPOINT AND SPOOL DATA SETS. - The JES2 of your system builds its data set names with a prefix other than
SYS1(its$DSNPRFXvalue). From mvsMF 1.4.0 on, the jobs API allocatesSYS1.HASPCKPTandSYS1.HASPACEitself when the procedure has no DD, and it looks only for these names.
In both cases, remove the two comment marks. The values in the shipped lines (UNIT=3350 with VOL=SER=MVS000 and VOL=SER=SPOOL1) are site values. Compare them with the JES2 procedure of your system before the first start, and change them to what JES2 uses. With mvsMF 1.4.0 or later on a system with the prefix SYS1, leave the lines as they are. A DD in the procedure wins over the allocation, so active lines do no harm either. “The JES2 data sets” in the HTTPD Reference has the details.
Missing HTTPPRM. If the DD HTTPPRM does not exist, the server writes
HTTPD020W CANNOT OPEN DD:HTTPPRM -- USING DEFAULTS
and starts with built-in defaults: port 8080 and no routes. A member that opens and cannot be read to the end gives HTTPD038E, and the server does not start.
Defining the Users and Profiles in RAKF
Goal: RAKF knows the identity of the started task and the profiles that the shipped routes name. This task has two parts, and the first matters more.
Which RAKF do you have? TK4- and TK5 have RAKF 1.2.x. MVS/CE has RAKF 2.0.0. The two differ in what you type:
| RAKF 1.2.x (TK4-, TK5) | RAKF 2.0.0 (MVS/CE) | |
| Password in the table USERS | Required | Blank |
| Where the password is kept | In clear text, in SYS1.SECURE.CNTL(USERS) | Not in the table |
| Profiles | Edit the member by hand | RDEFINE and PERMIT |
Table 8. RAKF 1.2.x and 2.0.0
The User of the Started Task
RAKF has no table of started tasks. Every started task runs under the same account, STC in the group STCGROUP, and on the stock profiles that group holds ALTER on every data set on the system. HTTPD replaces this identity at the start. It logs on the user STCUSER in the group STCGRP with RACINIT, without a password, and writes
HTTPD004I STC IDENTITY SET TO HTTPD/USER VIA RACINIT
The capture of “Starting HTTPD” shows it. If the user is not defined, the logon fails. The server writes HTTPD004W with the user, the group and a return code, and goes on. It then runs as the account it inherited, with far more access than you meant. A warning is all you get, and that is the danger. So a start without HTTPD004I is not a good start.
Add a line to the table SYS1.SECURE.CNTL(USERS). The columns are fixed: the user ID in 1 to 8, the group in 10 to 17, the password in 19 to 26, the Operations flag in 28 and the Special flag in 30. The first two lines in the next examples are a ruler and are not part of the member. On TK5, with a placeholder password that you replace:
1 2 3 123456789012345678901234567890 HTTPD USER pppppppp N
On MVS/CE, where the password stays blank:
1 2 3 123456789012345678901234567890 HTTPD USER N
Rules for the line:
- Choose the password as you would for any account of that group. HTTPD never uses it, because it logs on without one, but the account exists and can be tried. On RAKF 1.2.x the table keeps passwords in clear text, so give READ on
SYS1.SECURE.CNTLonly to the people who administer RAKF. - On RAKF 1.2.x a blank password is refused when the table is loaded.
S RAKFUSERends withRAKFUIDS2 INPUT DATA INVALID OR OUT OF SEQ., thenRAKFUIDSX ** PROGRAM TERMINATED **and an abend U0200. The echo of the card always shows********in the password column, empty or not, so the echo does not help. Nothing in the table is updated. When this happens at the IPL, RAKF 1.2.x has no user table and accepts every user ID. HTTPD 4.5.1 and later writeHTTPD042Wthen and refuse all logins (“A Security System That Accepts Any User ID”). Look forRAKFUIDS4 USER TABLE UPDATEDin the log after the IPL. - Keep Operations at
N. WithYthe account has the operations authority, which is access to data sets without a profile. - Keep both tables in ascending order, as RAKF requires. A table that RAKF rejects is not loaded (see the blank password above).
- Do not use the user ID
HTTPPRBorSTCfor a person. HTTPD usesHTTPPRBfor its own test logon at the start, and refuses a login asSTC(“A Security System That Accepts Any User ID”). - Keep
STCGRPequal to the group on theUSERSline, so that the two do not drift apart. RAKF takes the group that you request at the logon and does not check that the user is connected to it.
The user needs READ on the Parmlib data set and on whatever HTTPD opens before a client identity exists. The stock rule for data sets gives that. If you narrowed it, give the group READ on the Parmlib data set, or the start fails. The user does not need a profile for SVC 244: HTTPD returns the authorization under the account it took it with, not under STCUSER.
Another name or group goes into the start command: S HTTPD,STCUSER=name,STCGRP=group, or into the defaults of the procedure.
The Profiles
Every route of the Parmlib member that has a RES=class:resource needs a profile for that resource. The shipped member has one, the mvsMF console service:
MOD=MVSMF /zosmf/restconsoles/* AUTH=TOKEN RES=FACILITY:MVSMF.CONSOLE
The profile is checked against the identity of the client on every request, so the user of the started task needs none of them. A route whose resource has no profile is not denied. RAKF treats a resource without a profile as allowed, the check of the resource does nothing, and only the check of AUTH= is left. HTTPD says so at the start:
HTTPD425W NO PROFILE FOR FACILITY:MVSMF.CONSOLE -- /zosmf/restconsoles/* NOT GATED
With the shipped member this is what a system without the profile prints. Until the profile exists, every user who can log in may issue operator commands through mvsMF up to 1.3.0. From mvsMF 1.4.0 on, mvsMF checks the same profile itself and refuses every user until it exists, so the warning then concerns only this route. Define it. A start without the message does not prove that the profile is right. It proves only that the message is not there, so look at the table.
From HTTPD 4.5.0 the keyword RES_NOPROFILE=DENY turns the permissive reading into a refusal. Once the profiles are defined and the start prints no HTTPD425W, add the keyword to the member. A route whose profile is forgotten or not loaded yet then answers 403, and the start prints HTTPD426W NO PROFILE FOR class:resource -- path REFUSES ALL REQUESTS, instead of opening the route to everyone who can log in. Leave it off while a route still relies on the permissive reading. “Refusing a Route Whose Profile Is Missing” has the details. The shipped member has the keyword as a comment line.
On MVS/CE, the commands RDEFINE and PERMIT define a profile. Run them in a TSO batch step. The capture defines the console profile, a second one, HTTPD.ADMIN, which a route such as LOC=/admin/* could name, and a third, HTTPD.DENIED, that is defined and permitted to nobody:
RDEFINE MVSMF.CONSOLE CLASS(FACILITY) UACC(NONE)
RDEFINE: FACILITY profile defined: MVSMF.CONSOLE
RDEFINE: Run RAKFPROF to activate the changes
PERMIT MVSMF.CONSOLE CLASS(FACILITY) ID(ADMIN) ACCESS(READ)
PERMIT: access READ granted to FACILITY/MVSMF.CONSOLE
PERMIT: ID = ADMIN
PERMIT: Run RAKFPROF to activate the changes
RDEFINE HTTPD.ADMIN CLASS(FACILITY) UACC(NONE)
RDEFINE: FACILITY profile defined: HTTPD.ADMIN
RDEFINE: Run RAKFPROF to activate the changes
PERMIT HTTPD.ADMIN CLASS(FACILITY) ID(ADMIN) ACCESS(READ)
PERMIT: access READ granted to FACILITY/HTTPD.ADMIN
PERMIT: ID = ADMIN
PERMIT: Run RAKFPROF to activate the changes
RDEFINE HTTPD.DENIED CLASS(FACILITY) UACC(NONE)
RDEFINE: FACILITY profile defined: HTTPD.DENIED
RDEFINE: Run RAKFPROF to activate the changes
END
Each RDEFINE writes the universal line of a profile with UACC(NONE). Each PERMIT adds a line that gives READ to a group or a user, here ADMIN. Run RDEFINE first. The profile is not active yet: the reply says Run RAKFPROF to activate the changes. Choose the group of the people who may issue operator commands with care. READ on the console profile means every operator command, and nothing narrows it per command.
On TK5 these commands do not exist, and the member SYS1.SECURE.CNTL(PROFILES) is edited by hand. The columns are fixed: the class in 1 to 8, the resource in 9 to 52, the group in 53 to 60 and the permission in 61 to 66. The universal line of a profile has a blank group and comes first. The lines for the same profiles as above (the first two lines are a ruler):
1 2 3 4 5 6 123456789012345678901234567890123456789012345678901234567890123456 FACILITYHTTPD.ADMIN NONE FACILITYHTTPD.ADMIN ADMIN READ FACILITYHTTPD.DENIED NONE FACILITYMVSMF.CONSOLE NONE FACILITYMVSMF.CONSOLE ADMIN READ
Merge them into the member in ascending order. A line that is out of order stops the whole table from loading.
Reloading. The tables are read when the RAKF tasks start, so a change needs a start. The task RAKF reads both tables. RAKFPROF and RAKFUSER read one each, the profiles and the users. The capture shows the profile task on MVS/CE:
S RAKFPROF
$HASP100 RAKFPROF ON STCINRDR
RAKF0010I STC RAKFPROF STARTED USING DEFAULT STC ACCOUNT
$HASP373 RAKFPROF STARTED
IEF403I RAKFPROF - STARTED - TIME=00.40.36
RAKFPROF7 RAKF PROFILES UPDATED
$HASP395 RAKFPROF ENDED
IEF404I RAKFPROF - ENDED - TIME=00.40.36
RAKFPROF7 RAKF PROFILES UPDATED is the line that says the table is loaded.
What can go wrong. A profile for a group the person is not in: the request is refused with 403. The HTTPD Reference chapter “Routes and Authentication Policy” has the rules for the route modes, and Chapter 6, “Authentication and Security” shows how to use them.
The Document Root Disk
Goal: UFSD has a file system mounted at the path of DOCROOT, and the file system holds the welcome page. Skip the task if you do not use static files, and if you already have a webroot disk that you serve. The data set HTTPD.WEBROOT.UFS is very likely that disk, and no upgrade touches it.
The package carries the disk as a file, httpd-webroot.img. It is a 1 MB file system image with 256 blocks of 4096 bytes, and it holds one page, index.html: the welcome page. The image travels outside SMP, because SMP has no element type for a data set with undefined records, and because site content is the one thing an install must never replace.
Allocate the data set. Submit the job HTTPWEBR from the sample library: submit the member from HTTPD.SAMPLIB itself. Its important statement is
//WEBROOT DD DSN=HTTPD.WEBROOT.UFS,DISP=(NEW,CATLG), // UNIT=SYSDA,SPACE=(4096,256), // DCB=(DSORG=PS,RECFM=U,BLKSIZE=4096)
The block size 4096 is not a choice. The image is formatted with it, and UFSD compares the two when it mounts. A mismatch gives UFSD062E SUPERBLOCK VALIDATION FAILED FOR HTTPD.WEBROOT.UFS. The space is counted in blocks of 4096 and has a primary extent only: the file system is addressed by block number inside the primary extent, so a block in a secondary extent would never be reached. The job card has no NOTIFY operand on purpose. That operand is replaced only by TSO SUBMIT and by mvsMF, and any other way in gets a JCL error.
Upload the image. Use IND$FILE in binary mode, into the data set that the job allocated. IND$FILE takes the record format and the block size from the label of an existing data set, and it invents some only when the data set is not there. So allocating first is what pins the block size. FTP in binary mode and the zowe CLI in binary mode are other ways in. They are not measured for this data set, so the mount is the test. A text transfer destroys the image.
Mount it. The mount belongs to UFSD and not to HTTPD. Put the statement into the Parmlib member of UFSD (UFSDPRM0, unless you named another):
MOUNT DSN(HTTPD.WEBROOT.UFS) PATH(/www) MODE(RO)
and restart UFSD. The statement is the right one for the default DOCROOT=/www: it keeps the case of the path and creates the mount point. The operator form of the command, F UFSD,MOUNT DSN=...,PATH=..., upper-cases the path (it mounts /WWW) and does not create the directory. Paths are case sensitive, so the default document root finds nothing under /WWW. The UFSD User’s Guide describes both forms and the command that lists the mounts.
Verify. Start HTTPD (“Starting HTTPD”) and request the root path:
$ curl -s -D - -o /dev/null http://localhost:8080/
HTTP/1.1 200 OK
Date: Tue, 27 Oct 2026 05:41:41 GMT
Server: HTTPD Server
X-Powered-By: MVSLOVERS
Connection: keep-alive
Cache-Control: no-store
Content-Type: text/html
X-Content-Type-Options: nosniff
Transfer-Encoding: chunked
The status is 200 OK and the type is text/html. The body is the welcome page, which says “It works. The mainframe is online.” Chapter 3, “A First Request” reads such an answer line by line.
Replacing the disk later. Stop HTTPD and wait for $HASP395 HTTPD ENDED. Stop UFSD. Upload the new image into the same data set. Start UFSD, then HTTPD.
What can go wrong. UFSD062E at the mount: the block size is not 4096, or the file was sent in text mode. A 404 on every request: the mount point is not the document root, for example /WWW against /www. A start with HTTPD044W: UFSD is not running (see “UFSD Is Optional”).
Starting HTTPD
Goal: the server is up and does what you expect. The checklist before the first start:
- the load library is on the APF list, or RAKF is running (“Authority”);
- the procedure is in the procedure library, and the HASP data sets are right (“The Procedure and the Parmlib Member”);
- the Parmlib member exists and the DD points at it;
- the user and the profiles are in RAKF and the tables are reloaded (“Defining the Users and Profiles in RAKF”);
- UFSD runs and has mounted the webroot, if you use static files.
Start the task from the console:
S HTTPD
A start with another member or another Parmlib is S HTTPD,M=HTTPPRM1 or S HTTPD,D='MY.PARMLIB'. A healthy start looks like this:
S HTTPD
$HASP100 HTTPD ON STCINRDR
$HASP373 HTTPD STARTED
IEF403I HTTPD - STARTED - TIME=23.38.46
HTTPD000I HTTPD 4.5.1 (nnnnnnn) STARTING
HTTPD005I LIBC370 2.26.0 (3AA3B28)
HTTPD002I AUTHORIZED BY SVC (MODULE KEY 8)
HTTPD004I STC IDENTITY SET TO HTTPD/USER VIA RACINIT
RAKF0004 INVALID ATTEMPT TO ACCESS SYSTEM: USER:HTTPPRB
HTTPD036I MODULE MVSMF REGISTERED FOR /zosmf/info
HTTPD036I MODULE MVSMF REGISTERED FOR /zosmf/services/authenticate
HTTPD036I MODULE MVSMF REGISTERED FOR /zosmf/*
HTTPD054I LISTENING ON ANY PORT 8080
HTTPD061I STARTING SOCKET THREAD TCB(9AD080) TASK(162FC8) STACKSIZE(32768)
HTTPD061I STARTING WORKER(0ED7B0) TCB(9AD828) TASK(176FC8) STACKSIZE(65536)
HTTPD061I STARTING WORKER(174CC8) TCB(9A0CF8) TASK(187FC8) STACKSIZE(65536)
HTTPD061I STARTING WORKER(174C48) TCB(9A09C8) TASK(198FC8) STACKSIZE(65536)
HTTPD001I HTTPD 4.5.1 READY - SERVING /www
Read the lines in order:
HTTPD000I- The start. The version and the build stamp. The capture shows
nnnnnnnin place of the stamp (see below). HTTPD005I- The C library that HTTPD is linked with. Send the two lines with a problem report.
HTTPD002I- How the task got its authorization (“Authority”).
HTTPD004I- The identity of the task now:
HTTPD/USER. Without this line the task runs as the inherited account. RAKF0004- On TK5 (RAKF 1.2.x) and MVS/CE (RAKF 2.0.0), and only in 4.5.1 and later: the server tests the security system once, with a logon that must fail (see below and “A Security System That Accepts Any User ID”).
HTTPD036I- One line for each
MOD=route. HTTPD054I- The server listens on the port.
HTTPD061I- One line for the socket thread and each worker.
HTTPD001I- HTTPD is ready. The text after
SERVINGis the document root.
The member used in the capture had three mvsMF routes. The shipped member has four active routes, so a start with it shows the lines for the routes that you have.
The build stamp. The capture comes from a package that was built from the source of the release branch on a developer machine, with the version in the project file changed from 4.5.1-dev to 4.5.1. Its stamp is replaced by nnnnnnn in the capture, and the capture leaves out the line HTTPD006W BUILT FROM A MODIFIED WORKING TREE, which a build from a modified working tree writes after HTTPD005I. A start of the published package of 4.5.1 was not measured for this book. The version in your own HTTPD000I must be 4.5.1.
The line from RAKF. Since 4.5.1 the server tests the security system once at the start. It logs on the user HTTPPRB with a password that cannot be right. A system that checks refuses the logon. On TK5 (RAKF 1.2.x) and MVS/CE (RAKF 2.0.0) the refusal writes RAKF0004 INVALID ATTEMPT TO ACCESS SYSTEM: USER:HTTPPRB to the console, between HTTPD004I and the first HTTPD036I, as the capture shows. The line is expected, and no user HTTPPRB needs to exist. The capture comes from TK5. A first install of 4.5.1 on a throwaway MVS/CE system showed the same line in the same place. If the server writes HTTPD042W instead, the security software has accepted the test logon. On RAKF 1.2.x this happens when the user table is missing or was rejected at the IPL (“A Security System That Accepts Any User ID”). The server then refuses every login until the security software runs correctly and HTTPD has been restarted. Routes that need no login still answer.
A start that does not come up ends the task with a condition code other than 0, and 8 for a refused configuration. A clean stop ends with 0. The messages in front of a refused start say why. The most common ones:
HTTPD037E HTTPD IS ALREADY ACTIVE ON PORT n, THIS INSTANCE ENDS: another HTTPD already serves the port.HTTPD030I: the port is in use. The server waits and tries again. After the last try,HTTPD030Eends the instance. The keywordsBIND_SLEEPandBIND_TRIESset the wait and the number of tries. Both default to 10 and are limited to the range 1 to 100.HTTPD012E: no APF authorization (“Authority”).HTTPD411Efollowed byHTTPD420E: a route has a mode that does not exist.HTTPD048E: the retired keywordLOGINwith a value that used to require a login. ALOGINwithNONEor no value gives the warningHTTPD048Winstead. Convert the routes toAUTH=.
Restarting
To pick up a change of the Parmlib member, stop and start:
P HTTPD S HTTPD
Do not start before the stop has finished. Wait for $HASP395 HTTPD ENDED. A start that overlaps the end of the old task finds the port taken (HTTPD030I). Chapter 8, “Operating HTTPD” has the operator side: how to watch a running server, how to change a setting without a restart, and what every command prints.
What HTTPD Serves After the Install
With the shipped member and nothing else installed, HTTPD answers on the port 8080 as follows:
- A request for a path under
/zosmf/goes to mvsMF. Two of the four routes,/zosmf/infoand/zosmf/services/authenticate, haveAUTH=NONE. The other two need a login token (AUTH=TOKEN). Without mvsMF installed, each of these requests gives an error response and the messageHTTPD908E. - Every other path is a request for a static file, from the document root. With the webroot disk mounted, a request for
/returns the welcome page. Without UFSD, such a request fails. - A path that no route claims is public. A route without
AUTH=is public too. So do not add a route without a mode.
The display modules are not reachable. Nothing names them until you add a MOD= line. Chapter 3, “A First Request” sends the first requests. Chapter 4, “Configuring HTTPD” and Chapter 5, “Routes and Server Modules” change what is served, and Chapter 6, “Authentication and Security” says who may fetch it.
Problems at Installation
Chapter 12, “Troubleshooting” has the general table. The ones that belong to the install:
| What you see | What it means and what to do |
The allocation job waits with IEF099I | A running HTTPD has the library. Stop it with P HTTPD (“Stopping a Running HTTPD”). |
IEF287I ... NOT CATLGD 2 in the allocation job | The names exist. The new copies are not the libraries in use. Delete them by hand (“Allocating the Product Data Sets”). |
| The RECEIVE step ends with a return code that is not zero | The XMIT file was sent in text mode, or its record format is not FB 80 (“Sending the Two XMIT Files”). |
All steps end with 0 but HTTPD.LINKLIB has no members | A return code says that the job ran. List the members and the SMP record (“Verifying the Install”). |
HTTPD012E at the start | No APF authorization and no SVC (“Authority”). |
HTTPD002I AUTHORIZED BY SVC although the library is on the APF list | The library is on another volume than the APF entry (“Authority”). |
No HTTPD004I, or HTTPD004W instead | The user of the task is not defined in RAKF, or the logon failed (“Defining the Users and Profiles in RAKF”). |
HTTPD042W at the start, and every login gets 401 | RAKF 1.2.x accepts any user ID, because its user table is missing or was rejected. Correct the tables, IPL, and restart HTTPD (“A Security System That Accepts Any User ID”). |
HTTPD425W or HTTPD426W at the start | A route names a resource that has no profile (“Defining the Users and Profiles in RAKF”). |
HTTPD044W at the start | UFSD is not running (“UFSD Is Optional”). |
UFSD062E at the mount | The webroot data set has not the block size 4096, or the image was sent in text mode (“The Document Root Disk”). |
HTTPD020W at the start | The DD HTTPPRM is missing (“The Procedure and the Parmlib Member”). |
HTTPD014E, HTTPD015E or HTTPD016E at the start | The procedure has a DD that it must not have (“The Procedure and the Parmlib Member”). |
Table 9. Problems of the installation
To take HTTPD out of the system again, follow Chapter 11, “Removing HTTPD”.