ML07-0001-0

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:

  1. Read what is in the package (“What Is in the Package”) and what the system needs (“What You Need”).
  2. Send the two XMIT files to MVS (“Sending the Two XMIT Files”).
  3. Stop a running HTTPD, if there is one (“Stopping a Running HTTPD”).
  4. Allocate the product data sets (“Allocating the Product Data Sets”).
  5. 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”).
  6. Put the procedure and the Parmlib member in place (“The Procedure and the Parmlib Member”).
  7. Define the user and the profiles in RAKF (“Defining the Users and Profiles in RAKF”).
  8. Put the webroot disk on the system and mount it (“The Document Root Disk”).
  9. 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.

FileWhat it is
README.mdThe installation guide as a text file.
httpd-4.5.1-load.xmitThe five load modules, in a form that TSO RECEIVE reads. A little over 800,000 bytes.
httpd-4.5.1-samplib.xmitThe 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.jclAllocates the two libraries that SMP installs into. Run it once.
httpd-4.5.1-inst.jclThe install job: TSO RECEIVE of both XMIT files, then SMP RECEIVE, APPLY and ACCEPT.
httpd-webroot.imgThe 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:

ModuleWhat it is
HTTPDThe server. It is the only module that the started task names.
HTTPDSRVA display module for a browser. Route /.dsrv.
HTTPDMA display module for a terminal client. Route /.dm.
HTTPDMTTA display module for the master trace table. Route /.dmtt.
ABEND0C1A 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:

MemberWhat it is
HTTPDThe procedure of the started task (“The Procedure and the Parmlib Member”).
HTTPPRM0A Parmlib member to copy and edit.
HTTPWEBRA 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 setRole
HTTPD.LINKLIBThe 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.AHTTPLODThe distribution library: the copy that SMP keeps for the accepted level. Allocated by the allocation job.
HTTPD.HTTPLOADThe staging library. TSO RECEIVE creates it, SMP reads the modules from it, and the last step of the install job scratches it.
HTTPD.SAMPLIBThe sample library. TSO RECEIVE creates it. It is a plain library that SMP does not own.
HTTPD.WEBROOT.UFSThe 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

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.

Note: Only the FTP route is captured in this book. The zowe and IND$FILE routes are described here without a session.

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:

StepWhat it does
DELOLDDeletes 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.
RECV1TSO RECEIVE of the load XMIT into HTTPD.HTTPLOAD.
RECV2TSO RECEIVE of the sample XMIT into HTTPD.SAMPLIB.
RECVSMP RECEIVE. The SYSMOD travels inside the job and goes into the SMP inventory.
APPLYCHKSMP APPLY with CHECK: a dry run that changes nothing.
APPLYSMP APPLY: copies the five modules into HTTPD.LINKLIB.
ACCEPTSMP ACCEPT: copies them into HTTPD.AHTTPLOD and makes this level the one a RESTORE would return to.
CLEANUPScratches 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:

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 by S 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 with S 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 is STCGROUP: 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:

DDPurpose
STEPLIBHTTPD.LINKLIB. The load library of the server and of its modules. The package build writes the name into the procedure.
SYSUDUMP, SNAPDump output.
HTTPDERR, HTTPDOUT, HTTPDBG, HTTPSTATOutput of the server, to the spool.
HTTPDINDummy.
HTTPPRMThe Parmlib member: DSN=&D(&M), DISP=SHR, FREE=CLOSE.
HASPCKPT, HASPACE1Comment 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:

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 USERSRequiredBlank
Where the password is keptIn clear text, in SYS1.SECURE.CNTL(USERS)Not in the table
ProfilesEdit the member by handRDEFINE 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:

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:

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 nnnnnnn in 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 SERVING is 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:

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:

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 seeWhat it means and what to do
The allocation job waits with IEF099IA running HTTPD has the library. Stop it with P HTTPD (“Stopping a Running HTTPD”).
IEF287I ... NOT CATLGD 2 in the allocation jobThe 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 zeroThe 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 membersA return code says that the job ran. List the members and the SMP record (“Verifying the Install”).
HTTPD012E at the startNo APF authorization and no SVC (“Authority”).
HTTPD002I AUTHORIZED BY SVC although the library is on the APF listThe library is on another volume than the APF entry (“Authority”).
No HTTPD004I, or HTTPD004W insteadThe 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 401RAKF 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 startA route names a resource that has no profile (“Defining the Users and Profiles in RAKF”).
HTTPD044W at the startUFSD is not running (“UFSD Is Optional”).
UFSD062E at the mountThe webroot data set has not the block size 4096, or the image was sent in text mode (“The Document Root Disk”).
HTTPD020W at the startThe DD HTTPPRM is missing (“The Procedure and the Parmlib Member”).
HTTPD014E, HTTPD015E or HTTPD016E at the startThe 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”.