CICS Online Programming
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The reference material consulted while preparing these pages is listed in the section bibliography. |
This page is written against ISO/IEC 1989:2023 (edition 3, January 2023; an upcoming 4th edition is in ballot), which says nothing about CICS because transaction processing is not part of the language; against IBM Enterprise COBOL for z/OS 6.5 (PTFs through September 2026) on z/OS 3.2; and against IBM CICS Transaction Server for z/OS 6.x, whose documentation set (SSJL4D_6.x) lists releases 6.1, 6.2 and 6.3, 6.3 being the newest listed on 2026-10-20. GnuCOBOL 3.2 has no CICS, so nothing on this page was compiled and run as a transaction. All CICS code here is z/OS code and is labelled "z/OS; not run here". It was checked statement by statement against the CICS and Enterprise COBOL manuals named in the Source: lines. As a guard against plain COBOL mistakes, the CINQPGM program was also syntax-checked with GnuCOBOL 3.2 (cobc -fsyntax-only -Wall, no warnings) after each EXEC CICS block was replaced by CONTINUE and stand-in copybooks for DFHAID and the symbolic map were supplied; that check says nothing about how CICS behaves.
CICS is the transaction monitor in which most large online COBOL programs on the mainframe run: a clerk at a terminal, or a web or mobile client behind an API, sends a request, a short COBOL program answers it, and thousands of such requests are handled at the same time in one long-running region. This page explains that execution model, then the commands a COBOL program uses: terminal I/O with BMS maps, file control against VSAM, program control, and error handling. Everything is shown on the Circulation scenario of the section: CINQ, the transaction that answers "where is this book?" from a 3270 screen, reading the BOOKMAST KSDS through the BOOKREC layout of Copybooks, COPY and REPLACE. The batch counterpart of the same data set is in Indexed Files and VSAM and the z/OS landscape around it in Mainframe Environment Primer. Embedded SQL, the other statement family that a translator handles, is in Embedded SQL and Db2; how a compiled program is link-edited and run under Language Environment is in Compiling, Linking and Language Environment; calling between COBOL programs outside CICS is in Subprograms, CALL and Linkage.
Where the book is outdated: Taulli’s Modern Mainframe Development (2022, chapter 8) gives a short overview of CICS with SEND MAP, RECEIVE MAP and BMS macros, written against CICS 5.6 and Enterprise COBOL 6.3. The current release family is CICS TS 6.x, whose compiler-support page lists Enterprise COBOL 6.3, 6.4 and 6.5 as supported with CICS TS 6.3 (and with 5.6, 6.1 and 6.2). For COBOL, IBM now recommends the integrated CICS translator, because, as the CICS documentation puts it, the separate translator has not been updated for newer COBOL language. The overview in the book also leaves out what a working program needs: checking RESP after every command instead of letting a condition abend the task, the EIBCALEN test that makes the first and later entries of a pseudo-conversation different, and channels and containers as the modern way to pass data between programs. Those are covered below.
The CICS model: regions, transactions, tasks and programs
A region is a CICS address space, a long-running job or started task of z/OS (see the primer). Inside it CICS acts as a small operating system for transactions: it owns the terminals and the files that applications use, schedules work, and gives each piece of work the resources it asks for. A production system usually has several regions with different jobs. A terminal-owning region (TOR) holds the terminal sessions, application-owning regions (AOR) run the programs, and a file-owning region (FOR) can own the VSAM files; this split is a deployment choice and a program does not see it, because CICS routes the requests.
The four words that matter for a programmer are these.
| Term | Meaning |
|---|---|
Transaction |
A unit of work that the user starts by a four-character transaction identifier ( |
Task |
One execution of a transaction. CICS attaches a task for every request, runs the program for it, and discards the task when the program returns. Many tasks of the same transaction can run at the same time, each with its own working storage. |
Program |
A load module (a compiled COBOL program) that a task runs. A task can run several programs, one after the other ( |
Terminal or other resource |
The 3270 terminal (or an emulator), a file, a queue, a channel. The program refers to resources by name and CICS looks up the definition. |
Resource definitions (the transaction CINQ that starts program CINQPGM, the program and mapset definitions, the file BOOKMAST with the data set USERID.CIRC.BOOKMAST and the operations it allows, such as read and browse) are kept in the CICS system definition (CSD) and installed into the region; programs and mapsets can also be defined automatically on first use. The attribute names and the commands to define them are in the CICS resource-definition documentation, which this page does not reproduce. Nothing in the COBOL source says which data set BOOKMAST is: the program names the CICS file, and the definition connects it to the VSAM cluster. This is the biggest difference from batch, where the SELECT and the DD statement do this job.
Programs run under Language Environment, and a COBOL program used as a CICS application program has rules of its own. The CICS manual states that COBOL class definitions and methods (object-oriented COBOL) cannot be used, and refers to a separate topic, "COBOL programming restrictions and requirements", for the rest; this page does not reproduce that list. The practical consequence is that a CICS program does its terminal and file I/O with EXEC CICS commands and not with ACCEPT, DISPLAY or the COBOL file statements of batch. Working storage is allocated freshly for every task, and the program must be compiled with the RENT option (see the translator section below), because one copy of the code serves many tasks at once.
Conversational and pseudo-conversational design
A transaction that talks to a terminal user has a problem of time. A person reading a screen and typing the next entry takes seconds or minutes, and a computer counts that in eternities.
-
A conversational program sends a screen, waits inside the same task for the reply, and carries on. It is simple to write because its variables live from one screen to the next, but the task holds its storage and its resources, including any file record it has locked for update, for as long as the person thinks. IBM states that conversational transactions tie up storage and other resources for much longer than non-conversational ones, and they do not scale.
-
A pseudo-conversational program breaks the dialogue into a chain of short tasks. Each task receives one input, does the work, sends one output and ends. Between two tasks nothing at all is allocated to the user, and the terminal just waits. To make it look like one conversation, the program asks CICS to start the same transaction (or another) at the next input from this terminal, and passes along the data it will need.
The command that does both is EXEC CICS RETURN TRANSID('CINQ') COMMAREA(WS-COMM) LENGTH(LENGTH OF WS-COMM). TRANSID names the transaction CICS will start the next time the user presses an attention key; COMMAREA hands a copy of a data area to the first program of that next task. The next task finds it in the DFHCOMMAREA item of its LINKAGE SECTION and its length in EIBCALEN. When the program is started for the first time, nobody has passed anything, so EIBCALEN is zero: that is the standard test for "this is the first entry, send the blank screen". On every later entry EIBCALEN is the length of the data the previous task returned.
The next diagram shows the CINQ dialogue of this page from the first screen to leaving the transaction. Notice that three tasks run and that between them the program is not in memory for the user at all; only the terminal and a small copy of the communication area exist.
The rules that follow from this design are the things that go wrong first in a new CICS program.
-
Nothing survives a task except what is returned. Working storage is new for every task: a counter set in task 1 is gone in task 2 unless the program put it in the
COMMAREA(or in a queue, a temporary-storage record or a file). TheCOMMAREAofRETURNcan be 0 to 32,763 bytes; a length outside that range raisesLENGERR. -
COMMAREAis only a convenience. IBM notes that it is not recoverable, has no resource security and is not meant for large amounts of data, and suggests a channel as the more modern alternative (see below). -
The pseudo-conversation can be interrupted. If another transaction is started for the same terminal (for example by a queued request), it can take the place of the
TRANSIDthe program chose, unlessIMMEDIATEis given onRETURN. Design theCOMMAREAso that a program can detect unexpected input. -
COMMAREA,CHANNELandIMMEDIATEonRETURNonly work when the program returns to CICS, that is, when it is the top-level program of the task. Used in a program that was reached byLINK, they raiseINVREQ. -
Locks do not survive either. A record read for update is released when the task ends, so a user cannot hold a record "while the screen is on view". Pseudo-conversational programs re-read the record and compare it with the copy that was shown before they rewrite it.
The EXEC interface block
CICS gives every program a read-only control block, the EXEC interface block (EIB), with information about the task and about the last command. In COBOL the translator inserts it in the LINKAGE SECTION, so the program can simply use its fields by name; it must not change them. The fields used by this page are:
| Field | COBOL picture | Contents |
|---|---|---|
|
|
Length of the communication area passed from the previous program; binary zeros if none was passed. |
|
|
The attention identifier of the last terminal input: which key the operator pressed. Compare it with the |
|
|
The transaction identifier of the task. |
|
|
The terminal identifier. |
|
|
The cursor position at the last input, as an offset from the start of the screen. |
|
|
The response code of the last command, the same value a |
|
|
The qualifying code (more detail on why the condition happened). |
|
|
The function code of the last command, useful in an error report. |
|
|
The six-byte response code of the last command, for example the VSAM feedback after an |
A program should copy EIBRESP, EIBRESP2 and EIBFN into its own diagnostics at once, because the next command overwrites them.
Channels and containers
A COMMAREA is one anonymous block of at most 32,763 bytes. A channel is a named set of containers, and a container is a named piece of data with its own length. A program puts data in containers, names the channel on LINK, XCTL or RETURN, and the next program reads the containers by name. The structure is self-describing (the called program asks for what it needs), the data can be several items of different formats, and the size is not limited by the 32,763-byte COMMAREA rule; IBM presents channels as the modern alternative for new programs. Channel names and container names are 1 to 16 characters. If a program does not name a channel, it uses its current channel; the special name DFHTRANSACTION is a transaction channel that stays available to the whole task.
The next fragment is the calling side of a lookup program, CIRCAVL, that returns a BOOKREC for an id. It shows the three commands that are used together (z/OS; not run here). The called program issues GET CONTAINER without naming the channel, because it was invoked with one, and then PUT CONTAINER to return the record in another container of the same channel.
01 WS-KEY PIC 9(6).
01 WS-FLEN PIC S9(8) COMP.
...
EXEC CICS PUT CONTAINER('BOOKID') CHANNEL('CIRCCHAN')
FROM(WS-KEY) FLENGTH(LENGTH OF WS-KEY)
RESP(WS-RESP) RESP2(WS-RESP2)
END-EXEC
EXEC CICS LINK PROGRAM('CIRCAVL') CHANNEL('CIRCCHAN')
RESP(WS-RESP) RESP2(WS-RESP2)
END-EXEC
IF WS-RESP = DFHRESP(NORMAL)
MOVE LENGTH OF BOOK-RECORD TO WS-FLEN
EXEC CICS GET CONTAINER('BOOKREC') CHANNEL('CIRCCHAN')
INTO(BOOK-RECORD) FLENGTH(WS-FLEN)
RESP(WS-RESP) RESP2(WS-RESP2)
END-EXEC
END-IF
Source: CICS TS 6.x: PUT CONTAINER (CHANNEL); CICS TS 6.x: GET CONTAINER (CHANNEL); CICS TS 6.x: Basic examples of channels and containers
The details that matter when using GET CONTAINER: with INTO, FLENGTH is both input (the largest length the program accepts) and output (the actual length), and data longer than the area is truncated with LENGERR (RESP2 11); a container that does not exist gives CONTAINERERR (RESP2 10). With SET, CICS returns the address of its own copy of the data, which the program must not free and must not keep beyond the life of the channel. From CICS TS 6.2, PUT CONTAINER has APPEND and PREPEND options; without them an existing container is overwritten. Containers are not recoverable. IBM recommends putting the channel name, the container names and the data layouts in a copybook shared by caller and callee, which fits the copybook discipline of the section.
BMS: mapsets, maps and fields
Basic mapping support (BMS) separates the layout of a 3270 screen from the program that fills it. A map is one screen layout; a mapset groups maps and is the unit that CICS loads. The layout is written in assembler macros that are not part of COBOL:
-
DFHMSDbegins (and, withTYPE=FINAL, ends) a mapset and sets defaults for its maps. ItsTYPEoperand tells the assembler which of two outputs to produce;MODE=INOUTallows both sending and receiving;LANG=COBOLchooses the language of the symbolic map;TIOAPFX=YESincludes the 12-byte filler the program reserves for the terminal input/output area prefix;STORAGE=AUTOgives each map its own storage;CTRLsets 3270 characteristics such asFREEKB(unlock the keyboard) andFRSET(reset the modified-data tags). -
DFHMDIbegins one map: its size, and the line and column where it starts. -
DFHMDFdefines one field: its position, length, attributes and initial text. A field that has a name in column 1 becomes a data item of the program; one without a name is constant text (labels). Because every field starts with an attribute byte on the screen, a field at position (3,16) really begins at column 15, and a zero-length field withLENGTH=0ends the preceding input field (a "stopper").
The assembler is run twice for every mapset. With TYPE=MAP it produces the physical map, the load module CICS uses at run time to build the 3270 data stream. With TYPE=DSECT it produces the symbolic map, a COBOL copybook that the program includes. Many sites write TYPE=&SYSPARM and pass DSECT or MAP on the assembler’s SYSPARM option from the build procedure; the exact procedure is site-specific and belongs to the CICS-supplied map-assembly procedures, which this page does not reproduce.
The Circulation CINQ screen is a title line, one input field for the book id, five output fields (title, ISBN, copies, price, and where the book is), a message line and a line of key help. It is mapset CINQSET, map CINQMAP (z/OS; not run here). A character in column 72 continues a macro statement; the operands of the continuation line start in column 16.
CINQSET DFHMSD TYPE=&SYSPARM,MODE=INOUT,LANG=COBOL,TIOAPFX=YES, X
STORAGE=AUTO,CTRL=(FREEKB,FRSET)
CINQMAP DFHMDI SIZE=(24,80),LINE=1,COLUMN=1
DFHMDF POS=(1,1),ATTRB=(ASKIP,BRT), X
INITIAL='CIRCULATION - BOOK INQUIRY'
DFHMDF POS=(1,70),ATTRB=(ASKIP,NORM),INITIAL='CINQ'
DFHMDF POS=(3,1),ATTRB=(ASKIP,NORM),INITIAL='Book id . . .'
BOOKID DFHMDF POS=(3,16),LENGTH=6,ATTRB=(UNPROT,NUM,IC,FSET), X
JUSTIFY=(RIGHT,ZERO)
DFHMDF POS=(3,23),LENGTH=0,ATTRB=ASKIP
DFHMDF POS=(5,1),ATTRB=(ASKIP,NORM),INITIAL='Title . . . .'
TITLE DFHMDF POS=(5,16),LENGTH=30,ATTRB=(ASKIP,NORM)
DFHMDF POS=(6,1),ATTRB=(ASKIP,NORM),INITIAL='ISBN . . . .'
ISBN DFHMDF POS=(6,16),LENGTH=13,ATTRB=(ASKIP,NORM)
DFHMDF POS=(7,1),ATTRB=(ASKIP,NORM),INITIAL='Copies . . .'
COPIES DFHMDF POS=(7,16),LENGTH=3,ATTRB=(ASKIP,NORM)
DFHMDF POS=(8,1),ATTRB=(ASKIP,NORM),INITIAL='Price . . . .'
PRICE DFHMDF POS=(8,16),LENGTH=8,ATTRB=(ASKIP,NORM)
DFHMDF POS=(10,1),ATTRB=(ASKIP,NORM),INITIAL='Where is it?'
STATE DFHMDF POS=(10,16),LENGTH=40,ATTRB=(ASKIP,BRT)
MSG DFHMDF POS=(22,1),LENGTH=70,ATTRB=(ASKIP,BRT)
DFHMDF POS=(24,1),ATTRB=(ASKIP,NORM), X
INITIAL='ENTER=Inquire PF8=Next book PF3=Exit'
DFHMSD TYPE=FINAL
END
The notable DFHMDF operands in it: ATTRB combines the field’s protection (ASKIP auto-skip protected, PROT protected, UNPROT unprotected, so typing is allowed), its content class (NUM numeric shift only), its brightness (BRT, NORM, DRK), IC (initial cursor here) and FSET (the modified-data tag is on, so the field always comes back with the next input even if the user did not type). JUSTIFY=(RIGHT,ZERO) right-aligns what the operator types and fills the left with zeros, so 2 arrives as 000002, which suits a numeric key. INITIAL gives the constant text; when LENGTH is left out for a field with INITIAL, the length is that of the text. Colour and highlighting are also available through COLOR, HILIGHT and the MAPATTS and DSATTS operands of DFHMSD.
Source: CICS TS 6.x: Creating BMS maps; CICS TS 6.x: BMS macro DFHMSD; CICS TS 6.x: BMS macro DFHMDI
The symbolic map
The assembler turns each named field into a group of items in the copybook CINQSET. For every field NAME there are five items: NAMEL, a halfword with the length of the data typed (zero if the operator typed nothing; the program sets it to -1 to ask for the cursor there); NAMEF, a flag byte (also seen as NAMEA, the attribute byte the program can change); NAMEI, the data received; and NAMEO, the data to send. The input record CINQMAPI and the output record CINQMAPO redefine the same storage, which is why a program moves LOW-VALUES to the output record before it sets the fields it wants to send. Below is the copybook for CINQMAP in the usual form of a generated symbolic map for LANG=COBOL, written out by hand here: the exact text is produced by the assembler and can differ in detail, such as comments and the names of fillers.
01 CINQMAPI.
02 FILLER PIC X(12).
02 BOOKIDL COMP PIC S9(4).
02 BOOKIDF PICTURE X.
02 FILLER REDEFINES BOOKIDF.
03 BOOKIDA PICTURE X.
02 BOOKIDI PIC X(6).
02 TITLEL COMP PIC S9(4).
02 TITLEF PICTURE X.
02 FILLER REDEFINES TITLEF.
03 TITLEA PICTURE X.
02 TITLEI PIC X(30).
02 ISBNL COMP PIC S9(4).
02 ISBNF PICTURE X.
02 FILLER REDEFINES ISBNF.
03 ISBNA PICTURE X.
02 ISBNI PIC X(13).
02 COPIESL COMP PIC S9(4).
02 COPIESF PICTURE X.
02 FILLER REDEFINES COPIESF.
03 COPIESA PICTURE X.
02 COPIESI PIC X(3).
02 PRICEL COMP PIC S9(4).
02 PRICEF PICTURE X.
02 FILLER REDEFINES PRICEF.
03 PRICEA PICTURE X.
02 PRICEI PIC X(8).
02 STATEL COMP PIC S9(4).
02 STATEF PICTURE X.
02 FILLER REDEFINES STATEF.
03 STATEA PICTURE X.
02 STATEI PIC X(40).
02 MSGL COMP PIC S9(4).
02 MSGF PICTURE X.
02 FILLER REDEFINES MSGF.
03 MSGA PICTURE X.
02 MSGI PIC X(70).
01 CINQMAPO REDEFINES CINQMAPI.
02 FILLER PIC X(12).
02 FILLER PICTURE X(3).
02 BOOKIDO PIC X(6).
02 FILLER PICTURE X(3).
02 TITLEO PIC X(30).
02 FILLER PICTURE X(3).
02 ISBNO PIC X(13).
02 FILLER PICTURE X(3).
02 COPIESO PIC X(3).
02 FILLER PICTURE X(3).
02 PRICEO PIC X(8).
02 FILLER PICTURE X(3).
02 STATEO PIC X(40).
02 FILLER PICTURE X(3).
02 MSGO PIC X(70).
Source: CICS TS 6.x: Creating BMS maps
SEND MAP and RECEIVE MAP
SEND MAP merges the program’s data with the map and writes the screen. RECEIVE MAP reads what the operator typed and puts it in the symbolic map.
Option of SEND MAP |
Meaning |
|---|---|
|
The map (1 to 7 characters) and its mapset (also 1 to 7, without the suffix). If |
|
The symbolic output record. If omitted, the default is the map name with the suffix |
|
Clears the screen first and moves the cursor to the top left. |
|
Sends only the constants and defaults of the map (the blank form); no program data. |
|
Sends only the program’s data and leaves the constants on the screen as they are. A field whose data is |
|
With a value (a halfword offset from zero) puts the cursor there; without a value, at the field whose length item is -1. It overrides |
|
Unlocks the keyboard after the write; without it the keyboard stays locked. |
|
Sounds the terminal’s alarm. |
|
Resets the modified-data tags of all fields before the map data is written. |
RECEIVE MAP has MAP, MAPSET and INTO(area) (default: the map name with the suffix I). Its most common condition is MAPFAIL (response 36): the input had no data, which happens when the operator presses CLEAR or a PA key, or presses ENTER or a function key without typing anything and without a field whose modified-data tag is on. By default MAPFAIL, like most conditions, ends the task abnormally, which is why a program that receives a map tests RESP (see below) and why FSET on the key field of CINQMAP makes the usual ENTER deliver data. SEND MAP can raise INVMPSZ (the map is wider than the terminal) and INVREQ; a program that sends a map with FROM and no DATAONLY to a map without fields gets INVREQ.
Attention identifiers
Which key did the operator press? CICS puts the attention identifier in EIBAID. The copybook DFHAID that CICS supplies defines one named one-byte constant for each key, so the program compares by name, not by hexadecimal value: DFHENTER (ENTER), DFHCLEAR (CLEAR), DFHPA1 to DFHPA3, DFHPF1 to DFHPF24 and DFHPEN (selector pen or cursor select). The copybook is included in WORKING-STORAGE with COPY DFHAID. A second supplied copybook, DFHBMSCA, defines attribute-byte constants for programs that change the attribute of a field at run time through the NAMEA item. The two keys CLEAR and PA1 to PA3 do not send any data, so RECEIVE MAP fails with MAPFAIL after them; test EIBAID for these before the RECEIVE, as CINQPGM does for CLEAR and PF3.
Source: CICS TS 6.x: BMS constants
File control
All VSAM access under CICS goes through commands that name the CICS file, FILE('BOOKMAST'), and not through COBOL READ and WRITE. The record is moved to or from a data area of the program. Keys are given in RIDFLD (record identification field): a key for a KSDS, a relative byte address for an ESDS, a record number for an RRDS.
| Command | What it does |
|---|---|
|
Reads one record by key. |
|
Adds a record. For a keyed file |
|
Replaces the record just read with |
|
Deletes the record read for update (without |
|
Releases the lock of a |
|
Starts a browse at a position: |
|
Reads the next record of the browse; CICS updates |
|
Moves the position of a browse without ending it. |
|
Ends the browse and releases its resources. Every successful |
Browse and update differ from the batch idea of opening a file in I-O mode in two ways. There is no OPEN or CLOSE in the program: CICS opens the file when the region or a command needs it, so NOTOPEN (response 19) and DISABLED (84) are conditions the program has to expect. And the update protocol is a pair of commands under one task: a READ UPDATE that is not followed by REWRITE, DELETE or UNLOCK holds the record until the task ends, so the program should end its work with the record as quickly as it can.
The next fragment is the update of a book’s copies, as a checkout transaction would do it. If there are no copies left the program releases the lock instead of rewriting (z/OS; not run here).
EXEC CICS READ FILE('BOOKMAST') INTO(BOOK-RECORD)
RIDFLD(WS-KEY) UPDATE
RESP(WS-RESP) RESP2(WS-RESP2)
END-EXEC
EVALUATE TRUE
WHEN WS-RESP = DFHRESP(NORMAL) AND BOOK-COPIES > 0
SUBTRACT 1 FROM BOOK-COPIES
EXEC CICS REWRITE FILE('BOOKMAST')
FROM(BOOK-RECORD)
RESP(WS-RESP) RESP2(WS-RESP2)
END-EXEC
WHEN WS-RESP = DFHRESP(NORMAL)
EXEC CICS UNLOCK FILE('BOOKMAST')
RESP(WS-RESP) RESP2(WS-RESP2)
END-EXEC
MOVE "No copy is on the shelf." TO WS-MSG-TEXT
WHEN WS-RESP = DFHRESP(NOTFND)
MOVE "Unknown book id." TO WS-MSG-TEXT
WHEN OTHER
PERFORM UNEXPECTED-ERROR
END-EVALUATE
Source: CICS TS 6.x: READ command; CICS TS 6.x: REWRITE command; CICS TS 6.x: WRITE command; CICS TS 6.x: DELETE command; CICS TS 6.x: STARTBR command; CICS TS 6.x: READNEXT command; CICS TS 6.x: ENDBR command
The conditions of READ that a program must be ready for are NOTFND (13: no such key), FILENOTFOUND (12: the file is not defined), DISABLED, NOTOPEN, LENGERR (22: the record is longer than the area, or LENGTH is missing for variable records), INVREQ (16: for example UPDATE on a file defined as read-only, or a KEYLENGTH mismatch; RESP2 says which), IOERR (17: usually a hardware or VSAM error), ILLOGIC (21: a VSAM error that fits no other condition; EIBRCODE holds the details) and DUPKEY (15: a record reached by a non-unique alternate index, with another following). The file-status codes of batch (see File Status Codes) do not exist here: RESP and RESP2 take their place.
Program control: LINK, XCTL and RETURN
CICS programs are built from many small programs, and three commands move between them.
-
LINK PROGRAM('name')calls another program at the next lower logical level and expects control back, like aCALL.COMMAREA(area) LENGTH(n)passes a data area, orCHANNEL('name')a channel. The called program receives theCOMMAREAinDFHCOMMAREA(it must use that name) and should testEIBCALEN; IBM recommends keeping theCOMMAREAbelow 24 KB, and warns not to use aLENGTHof 0. -
XCTL PROGRAM('name')transfers control to another program at the same level and does not return. The calling program is released, and the called one can receive aCOMMAREAor channel in the same way. It is the way a menu program hands a task over to the program of the chosen option. -
RETURNends the program. Without options it gives control back to the caller (or to CICS, ending the task); withTRANSIDit also names the transaction to start at the next terminal input (see above).
Their conditions are the same kind of mistakes: PGMIDERR (27) if the program is not defined, is disabled or cannot be loaded; LENGERR (22) for an invalid length; NOTAUTH (70) if the security check on the program fails; INVREQ and CHANNELERR for misuse of options and bad channel names. LINK can also raise SYSIDERR, TERMERR and ROLLEDBACK when the program is remote.
The next fragment links to CIRCFINE, a program that returns the overdue fine for a member, with a COMMAREA (z/OS; not run here). The first test of CIRCFINE would be IF EIBCALEN = 0, in which case it ends with an error code instead of reading a missing area.
01 FINE-AREA.
05 FA-MEMBER-ID PIC 9(6).
05 FA-DAYS-OVERDUE PIC 9(3).
05 FA-FINE PIC 9(5)V99.
05 FA-RETURN-CODE PIC 9(2).
...
MOVE MEMBER-ID TO FA-MEMBER-ID
EXEC CICS LINK PROGRAM('CIRCFINE')
COMMAREA(FINE-AREA) LENGTH(LENGTH OF FINE-AREA)
RESP(WS-RESP) RESP2(WS-RESP2)
END-EXEC
IF WS-RESP NOT = DFHRESP(NORMAL)
PERFORM UNEXPECTED-ERROR
END-IF
A CALL of a COBOL subprogram (see Subprograms, CALL and Linkage) is also possible inside a task, and is faster than LINK, but the called program is then part of the same load unit and cannot be distributed or secured separately; LINK is the choice for a program that other transactions, other regions or non-COBOL clients are to call.
Handling conditions: RESP and RESP2 instead of HANDLE CONDITION
When a command cannot do what it was asked, CICS raises a condition. By default most conditions end the task abnormally (an AEIx abend) with a dump. There are two ways to take over.
-
The old way is
HANDLE CONDITION, which tells CICS to branch to a paragraph when a condition occurs. It is still in the command summary, under exception support, but it makes the control flow depend on commands that executed earlier, the branches go to labels instead of returning, and the setting is easy to lose when programs are linked. New code does not use it. -
The way used by this page is the
RESPandRESP2options on each command.RESP(data-area)receives the response code of the command andRESP2(data-area)a qualifier, both as halfword or fullword binary items (PIC S9(8) COMP). WithRESPpresent, a condition does not abend the task: control continues with the next statement and the program decides.NOHANDLEalso suppresses the default action but gives no information.
The program does not compare the number with a literal; the translator provides DFHRESP(name), which it replaces by the number of the named condition at translation time, so the program reads like EVALUATE WS-RESP WHEN DFHRESP(NOTFND). The conditions met in this page and their response numbers:
DFHRESP(...) |
Number | Typical cause |
|---|---|---|
|
0 |
The command succeeded. |
|
12 |
The file is not defined to CICS. |
|
13 |
No record has the key. |
|
14 |
|
|
15 |
A record reached through a non-unique alternate index has another with the same key after it. |
|
16 |
The request is invalid; |
|
17 |
An I/O error, usually VSAM or hardware. |
|
19 |
The file is closed, quiesced or failed to open. |
|
20 |
|
|
21 |
A VSAM error that fits no other condition; see |
|
22 |
A length is wrong or the data was truncated. |
|
27 |
The program is not defined, disabled or cannot be loaded. |
|
36 |
|
|
53 |
The remote system is unknown or unavailable. |
|
70 |
A security check failed. |
|
84 |
The resource is disabled. |
|
110 |
The container does not exist ( |
|
122 |
The channel name has an illegal character. |
These numbers are given by the command pages of the CICS documentation; a program tests the names and never the numbers. Three practices follow. First, test RESP after every command that can fail, because once RESP is coded nothing else will tell you. Second, treat the conditions you expect (NOTFND, MAPFAIL, ENDFILE) as normal branches and every other one as a defect: report EIBRESP, EIBRESP2, EIBFN and EIBRCODE, and either end the task with EXEC CICS ABEND ABCODE('xxxx') (the transaction is backed out and the abend code identifies your program) or show an error screen and write a log record, as appropriate. Third, never reuse the RESP field between a command and its test: in CINQPGM the response of READNEXT is copied before ENDBR, because ENDBR would overwrite it.
The Circulation CINQ transaction
Now the pieces together. CINQ is the pseudo-conversational transaction that answers "where is this book?". The operator types a book id and presses ENTER; PF8 shows the next book in key order (a browse); PF3 or CLEAR ends. The answer to "where" is derived from BOOKREC: a withdrawn book is out of the collection, a book with no copies left is on loan, any other is on the shelf. The mapset is CINQSET above; the program below is CINQPGM, and the transaction CINQ is defined to start it (z/OS; not run here). BOOKREC is the 60-byte copybook of the section.
IDENTIFICATION DIVISION.
PROGRAM-ID. CINQPGM.
* CINQ - Circulation book inquiry (z/OS; not run here).
* Pseudo-conversational: one task per screen interaction.
DATA DIVISION.
WORKING-STORAGE SECTION.
COPY DFHAID.
COPY CINQSET.
COPY BOOKREC.
01 WS-COMM.
05 WS-LAST-ID PIC 9(6).
01 WS-KEY PIC 9(6).
01 WS-RESP PIC S9(8) COMP.
01 WS-RESP2 PIC S9(8) COMP.
01 WS-BR-RESP PIC S9(8) COMP.
01 WS-END-RESP PIC S9(8) COMP.
01 WS-COPIES-ED PIC ZZ9.
01 WS-PRICE-ED PIC ZZZ9.99.
01 WS-RESP-ED PIC Z(7)9.
01 WS-RESP2-ED PIC Z(7)9.
01 WS-MSG-TEXT PIC X(70).
01 WS-BYE PIC X(24)
VALUE "CINQ ended. Goodbye.".
LINKAGE SECTION.
01 DFHCOMMAREA.
05 CA-LAST-ID PIC 9(6).
PROCEDURE DIVISION.
MAIN-PARA.
IF EIBCALEN = 0
PERFORM FIRST-ENTRY
ELSE
MOVE CA-LAST-ID TO WS-LAST-ID
EVALUATE EIBAID
WHEN DFHCLEAR
WHEN DFHPF3
PERFORM END-CONVERSATION
WHEN DFHENTER
PERFORM PROCESS-ENTER
WHEN DFHPF8
PERFORM NEXT-BOOK
WHEN OTHER
MOVE "That key is not active." TO WS-MSG-TEXT
PERFORM SHOW-MESSAGE
END-EVALUATE
END-IF
EXEC CICS RETURN TRANSID('CINQ')
COMMAREA(WS-COMM) LENGTH(LENGTH OF WS-COMM)
END-EXEC.
FIRST-ENTRY.
MOVE ZERO TO WS-LAST-ID
EXEC CICS SEND MAP('CINQMAP') MAPSET('CINQSET')
MAPONLY ERASE FREEKB
END-EXEC.
PROCESS-ENTER.
EXEC CICS RECEIVE MAP('CINQMAP') MAPSET('CINQSET')
INTO(CINQMAPI) RESP(WS-RESP) RESP2(WS-RESP2)
END-EXEC
EVALUATE WS-RESP
WHEN DFHRESP(NORMAL)
PERFORM LOOKUP-BOOK
WHEN DFHRESP(MAPFAIL)
MOVE "Type a book id and press ENTER."
TO WS-MSG-TEXT
PERFORM SHOW-MESSAGE
WHEN OTHER
PERFORM UNEXPECTED-ERROR
END-EVALUATE.
LOOKUP-BOOK.
IF BOOKIDL = 0 OR BOOKIDI NOT NUMERIC
MOVE "The book id must be six digits." TO WS-MSG-TEXT
PERFORM SHOW-MESSAGE
ELSE
MOVE BOOKIDI TO WS-KEY
PERFORM READ-BOOK
END-IF.
READ-BOOK.
EXEC CICS READ FILE('BOOKMAST') INTO(BOOK-RECORD)
RIDFLD(WS-KEY) RESP(WS-RESP) RESP2(WS-RESP2)
END-EXEC
EVALUATE WS-RESP
WHEN DFHRESP(NORMAL)
PERFORM SHOW-BOOK
WHEN DFHRESP(NOTFND)
MOVE SPACES TO WS-MSG-TEXT
STRING "Book " WS-KEY " is not in the catalogue."
DELIMITED BY SIZE INTO WS-MSG-TEXT
PERFORM SHOW-MESSAGE
WHEN DFHRESP(NOTOPEN)
WHEN DFHRESP(DISABLED)
MOVE "The book file is not available now."
TO WS-MSG-TEXT
PERFORM SHOW-MESSAGE
WHEN OTHER
PERFORM UNEXPECTED-ERROR
END-EVALUATE.
NEXT-BOOK.
MOVE WS-LAST-ID TO WS-KEY
EXEC CICS STARTBR FILE('BOOKMAST') RIDFLD(WS-KEY) GTEQ
RESP(WS-RESP) RESP2(WS-RESP2)
END-EXEC
EVALUATE WS-RESP
WHEN DFHRESP(NORMAL)
PERFORM READ-NEXT-BOOK
WHEN DFHRESP(NOTFND)
MOVE "There is no later book." TO WS-MSG-TEXT
PERFORM SHOW-MESSAGE
WHEN OTHER
PERFORM UNEXPECTED-ERROR
END-EVALUATE.
READ-NEXT-BOOK.
EXEC CICS READNEXT FILE('BOOKMAST') INTO(BOOK-RECORD)
RIDFLD(WS-KEY) RESP(WS-RESP) RESP2(WS-RESP2)
END-EXEC
* The first READNEXT returns the book already on the screen.
IF WS-RESP = DFHRESP(NORMAL) AND BOOK-ID = WS-LAST-ID
EXEC CICS READNEXT FILE('BOOKMAST') INTO(BOOK-RECORD)
RIDFLD(WS-KEY) RESP(WS-RESP) RESP2(WS-RESP2)
END-EXEC
END-IF
MOVE WS-RESP TO WS-BR-RESP
EXEC CICS ENDBR FILE('BOOKMAST') RESP(WS-END-RESP)
END-EXEC
EVALUATE WS-BR-RESP
WHEN DFHRESP(NORMAL)
PERFORM SHOW-BOOK
WHEN DFHRESP(ENDFILE)
MOVE "That was the last book." TO WS-MSG-TEXT
PERFORM SHOW-MESSAGE
WHEN OTHER
MOVE WS-BR-RESP TO WS-RESP
PERFORM UNEXPECTED-ERROR
END-EVALUATE.
SHOW-BOOK.
MOVE BOOK-ID TO WS-LAST-ID
MOVE LOW-VALUES TO CINQMAPO
MOVE BOOK-ID TO BOOKIDO
MOVE BOOK-TITLE TO TITLEO
MOVE BOOK-ISBN TO ISBNO
MOVE BOOK-COPIES TO WS-COPIES-ED
MOVE WS-COPIES-ED TO COPIESO
MOVE BOOK-PRICE TO WS-PRICE-ED
MOVE WS-PRICE-ED TO PRICEO
EVALUATE TRUE
WHEN BOOK-WITHDRAWN
MOVE "Withdrawn from the collection" TO STATEO
WHEN BOOK-COPIES = 0
MOVE "All copies are on loan" TO STATEO
WHEN OTHER
MOVE "On the shelf" TO STATEO
END-EVALUATE
MOVE "Book found." TO MSGO
PERFORM SEND-DATA.
SHOW-MESSAGE.
MOVE LOW-VALUES TO CINQMAPO
MOVE SPACES TO TITLEO ISBNO COPIESO PRICEO STATEO
MOVE WS-MSG-TEXT TO MSGO
MOVE -1 TO BOOKIDL
EXEC CICS SEND MAP('CINQMAP') MAPSET('CINQSET')
FROM(CINQMAPO) DATAONLY CURSOR ALARM FREEKB
END-EXEC.
SEND-DATA.
MOVE -1 TO BOOKIDL
EXEC CICS SEND MAP('CINQMAP') MAPSET('CINQSET')
FROM(CINQMAPO) DATAONLY CURSOR FREEKB
END-EXEC.
UNEXPECTED-ERROR.
MOVE WS-RESP TO WS-RESP-ED
MOVE WS-RESP2 TO WS-RESP2-ED
MOVE SPACES TO WS-MSG-TEXT
STRING "Unexpected CICS error, RESP=" WS-RESP-ED
" RESP2=" WS-RESP2-ED
DELIMITED BY SIZE INTO WS-MSG-TEXT
PERFORM SHOW-MESSAGE.
END-CONVERSATION.
EXEC CICS SEND TEXT FROM(WS-BYE) LENGTH(LENGTH OF WS-BYE)
ERASE FREEKB
END-EXEC
EXEC CICS RETURN
END-EXEC.
What to notice in it, in order of the program:
-
MAIN-PARAis the whole control structure of a pseudo-conversational program:EIBCALEN = 0means the first entry; otherwise the previousCOMMAREAis copied fromDFHCOMMAREAinto working storage andEIBAIDchooses the action withEVALUATE. The program ends every non-final path withRETURN TRANSID('CINQ'), so the chain continues. StackedWHENclauses (DFHCLEARandDFHPF3) share one action. -
DFHCOMMAREAin theLINKAGE SECTIONhas no storage on the first entry (EIBCALENis zero), so it is never touched there. The program keeps its ownWS-COMM, which is also what it returns: the id of the book on view, six bytes. -
PROCESS-ENTERtestsRESPafterRECEIVE MAP.MAPFAILis an expected outcome and gets a friendly message; any other nonzero response goes toUNEXPECTED-ERROR, which reportsRESPandRESP2on the screen. -
LOOKUP-BOOKvalidates the input (BOOKIDL = 0andBOOKIDI NOT NUMERIC) before it touches the file, because the key field is typed by a person. -
READ-BOOKhandles the file conditions by name:NOTFNDis a message to the user,NOTOPENandDISABLEDsay the file is not available now, and everything else is unexpected. -
NEXT-BOOKandREAD-NEXT-BOOKshow the browse:STARTBRat the id on view withGTEQ, oneREADNEXT(which returns that same book), a secondREADNEXTfor the next one, andENDBRin all cases once the browse started;ENDFILEis the "last book" message. -
SEND-DATAandSHOW-MESSAGEuseDATAONLY, so the labels are not resent, and set the length itemBOOKIDLto -1 so that the cursor returns to the input field. OnlySHOW-MESSAGEusesALARM. -
The record layout is the same
BOOKRECcopybook as in the batch programs. A change to the record is a change to the copybook, and every online and batch program that includes it needs a recompile; this is the case for the copybook rule of the section.
An interaction as the operator sees it, by key (z/OS; not run here; the screen text is what the program above sends):
CINQ + ENTER -> blank map, cursor on Book id
000002 + ENTER -> Title COBOL BASICS
Copies 2 Where is it? On the shelf
000099 + ENTER -> message "Book 000099 is not in the catalogue."
PF8 -> shows the book after the one on view
000004 + ENTER -> "Withdrawn from the collection"
PF3 -> "CINQ ended. Goodbye."
Preparing a CICS program: the integrated translator
A COBOL program with EXEC CICS statements is not valid COBOL until the commands are translated into calls. Historically a separate CICS translator ran as a step before the compiler. The Enterprise COBOL compiler now contains the integrated CICS translator: with the CICS compiler option the compiler turns the EXEC CICS commands into comments and generates the calls, so translation and compilation are one step. The compiler options that the Programming Guide documents for this are:
-
CICSenables the integrated translator. It can be given in the compiler invocation, on aCBLorPROCESSstatement (CBL CICS), or as an installation default, but IBM advises against the installation default, because the option changes the way a non-CICS program is compiled. A suboption string can pass translator options. UseNOCICSonly if you ran the separate translator first; otherwise the compiler discards the CICS statements it finds. -
RENTandNODYNAMmust be in effect withCICS. The Programming Guide says that specifyingDYNAMorNORENTmakes the compiler forceNODYNAMandRENT. A fix (PTF) of September 2026 allowsDYNAMtogether withCICS, as listed in Compilers and Dialects; check the current Programming Guide text for that option combination before relying on either behaviour. -
The step needs the data set with the translator services in
STEPLIB(for example the CICSSDFHLOADlibrary) unless it is in the link list. The JCL is in JCL for COBOL Programmers and the compile-and-link flow in Compiling, Linking and Language Environment. -
WORD(CICS)makes the compiler flag language elements that CICS does not support. -
Under the integrated translator the old
XOPTStranslator option is replaced by theCICScompiler option, and many options that only controlled the translator’s own listing no longer apply.
The CICS documentation lists the supported compilers in its compiler-changes page: Enterprise COBOL for z/OS 6.5, 6.4 and 6.3 are supported on CICS TS 6.3 (and on 5.6, 6.1 and 6.2). Java-based object-oriented COBOL (classes and methods) cannot be used in a CICS application. One source file can serve both CICS and batch by using the compilation variable that the CICS option sets: the example in Compiler Directives and Conditional Compilation selects EXEC CICS READ or a READ statement with >>IF IGY-CICS.
Source: Enterprise COBOL for z/OS 6.5 Programming Guide: Compiling with the CICS option; CICS TS 6.x: The integrated CICS translator; CICS TS 6.x: Changes to CICS support for application programming languages
The maps are assembled by the High Level Assembler (twice, as seen above), and the program and the physical mapset are link-edited into the CICS load library; after that the new copy of the program is loaded for new tasks, for example with the CEMT command SET PROGRAM(CINQPGM) NEWCOPY. The CICS-supplied transactions are also the debugging tools of an online programmer: CEDF steps through a program command by command and shows the arguments and the RESP of each, and CECI and CEMT issue commands and inspect resources. The practical debugging advice of the section is in Debugging and Troubleshooting.
Exposing COBOL as APIs
A CICS program such as CIRCAVL, written with a COMMAREA or a channel and no direct terminal I/O, can be called from outside CICS. This is the usual first step of modernization, because it leaves the tested COBOL logic where it is and puts a modern interface in front of it. Two routes, in brief:
-
CICS web services map the data of a
COMMAREAor channel to a web-service message so that a client calls the program over HTTP; the details are in the CICS documentation and are not covered here. The mapping between the COBOL layout and the message comes from the copybook, which is another reason to keep record layouts in copybooks. -
IBM z/OS Connect is a framework that exposes z/OS assets, among them CICS programs, as RESTful APIs, and also lets z/OS programs call REST APIs. Its Eclipse-based API toolkit guides you through importing COBOL copybooks, PL/I include files or whole programs for CICS, and through customizing the service interface.
Both only need the program to be a good CICS citizen: no terminal I/O in the business logic, a layout in a copybook, and RESP handling that returns an error code instead of abending. The CIRCAVL / CINQ split shown above (a service program plus a screen program) is that shape. Where this fits the larger picture, with the strangler-fig and anti-corruption-layer techniques that wrap such programs, is in Modernization Strategies; the JSON side is in JSON GENERATE and PARSE.
Common mistakes
-
Keeping state in working storage. The next task starts with fresh storage. Whatever the next screen needs goes in the
COMMAREAor a channel. -
Using
COMMAREAfields on the first entry. WithEIBCALEN = 0DFHCOMMAREAhas no storage behind it; testEIBCALENfirst. -
Not coding
RESP. A program with the default handling abends onNOTFND,MAPFAILandNOTOPEN, usually with an abend code the user cannot interpret. Not testing it after coding it is worse. -
Testing
EIBAIDafterRECEIVE MAP. CLEAR and the PA keys send no data and raiseMAPFAIL; check the key first. -
Forgetting
ENDBR. ASTARTBRwithoutENDBRkeeps the browse (and its resources) until the task ends, and a secondSTARTBRwith the sameREQIDis anINVREQ. -
Overwriting
RESPbefore reading it. The next command, includingENDBR, replaces it; save it first. -
Holding a
READ UPDATEacross a screen. The lock ends with the task. Re-read and compare before rewriting. -
Mixing batch and CICS I/O.
READ,OPEN,DISPLAYandACCEPTbelong to batch; online programs useEXEC CICScommands. -
Putting the
CICSoption in the installation defaults. It changes how every non-CICS program is compiled; give it per program. -
Sending the whole map every time.
DATAONLYkeeps the constants on the screen and sends less; useERASEonly when the screen has to be redrawn. -
Using
HANDLE CONDITIONin new code. UseRESPandRESP2. -
Using the numeric value of a response. Test
DFHRESP(NOTFND), not 13.
References
-
CICS TS 6.x: Changes to CICS support for application programming languages
-
Enterprise COBOL for z/OS 6.5 Programming Guide: Compiling with the CICS option
-
CICS TS 6.x: EXEC CICS command format and programming considerations
-
Tom Taulli, Modern Mainframe Development, O’Reilly Media, 2022 (chapter 8, consulted for the topics only)