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 (TRANSID), such as CINQ. The transaction definition names the first program to run. The user types the identifier, or a previous program names it in RETURN TRANSID.

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 (XCTL) or nested (LINK).

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.

sequenceDiagram actor U as Operator at a 3270 terminal participant C as CICS region participant P as CINQPGM task U->>C: Types CINQ and presses ENTER C->>P: Attach task 1, EIBCALEN = 0 P->>C: SEND MAP CINQMAP, MAPONLY, ERASE C-->>U: Blank inquiry screen P->>C: RETURN TRANSID(CINQ) COMMAREA(WS-COMM) Note over C,P: Task 1 ends. The terminal waits and no program storage is held. U->>C: Types book id 000002 and presses ENTER C->>P: Attach task 2, EIBCALEN = 6, EIBAID = DFHENTER P->>C: RECEIVE MAP, READ FILE(BOOKMAST) P->>C: SEND MAP DATAONLY C-->>U: Title, copies and where the book is P->>C: RETURN TRANSID(CINQ) COMMAREA(WS-COMM) Note over C,P: Task 2 ends. U->>C: Presses PF3 C->>P: Attach task 3, EIBAID = DFHPF3 P->>C: SEND TEXT, RETURN without TRANSID C-->>U: Goodbye, the conversation is over

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). The COMMAREA of RETURN can be 0 to 32,763 bytes; a length outside that range raises LENGERR.

  • COMMAREA is 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 TRANSID the program chose, unless IMMEDIATE is given on RETURN. Design the COMMAREA so that a program can detect unexpected input.

  • COMMAREA, CHANNEL and IMMEDIATE on RETURN only 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 by LINK, they raise INVREQ.

  • 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

EIBCALEN

PIC S9(4) COMP

Length of the communication area passed from the previous program; binary zeros if none was passed.

EIBAID

PIC X(1)

The attention identifier of the last terminal input: which key the operator pressed. Compare it with the DFHAID constants.

EIBTRNID

PIC X(4)

The transaction identifier of the task.

EIBTRMID

PIC X(4)

The terminal identifier.

EIBCPOSN

PIC S9(4) COMP

The cursor position at the last input, as an offset from the start of the screen.

EIBRESP

PIC S9(8) COMP

The response code of the last command, the same value a RESP option returns.

EIBRESP2

PIC S9(8) COMP

The qualifying code (more detail on why the condition happened).

EIBFN

PIC X(2)

The function code of the last command, useful in an error report.

EIBRCODE

PIC X(6)

The six-byte response code of the last command, for example the VSAM feedback after an ILLOGIC condition.

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

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:

  • DFHMSD begins (and, with TYPE=FINAL, ends) a mapset and sets defaults for its maps. Its TYPE operand tells the assembler which of two outputs to produce; MODE=INOUT allows both sending and receiving; LANG=COBOL chooses the language of the symbolic map; TIOAPFX=YES includes the 12-byte filler the program reserves for the terminal input/output area prefix; STORAGE=AUTO gives each map its own storage; CTRL sets 3270 characteristics such as FREEKB (unlock the keyboard) and FRSET (reset the modified-data tags).

  • DFHMDI begins one map: its size, and the line and column where it starts.

  • DFHMDF defines 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 with LENGTH=0 ends 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.

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).

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

MAP(name), MAPSET(name)

The map (1 to 7 characters) and its mapset (also 1 to 7, without the suffix). If MAPSET is left out, CICS uses the map name as the mapset name.

FROM(area)

The symbolic output record. If omitted, the default is the map name with the suffix O.

ERASE

Clears the screen first and moves the cursor to the top left.

MAPONLY

Sends only the constants and defaults of the map (the blank form); no program data.

DATAONLY

Sends only the program’s data and leaves the constants on the screen as they are. A field whose data is LOW-VALUES is not changed.

CURSOR

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 IC in DFHMDF.

FREEKB

Unlocks the keyboard after the write; without it the keyboard stays locked.

ALARM

Sounds the terminal’s alarm.

FRSET

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.

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

READ FILE INTO RIDFLD

Reads one record by key. UPDATE reads it for a later REWRITE or DELETE and holds a lock on it until the REWRITE, DELETE, UNLOCK or end of the task or sync point. GENERIC (with KEYLENGTH) matches the leading part of the key; GTEQ returns the next higher key if there is no exact match; EQUAL requires an exact match. INTO copies the record to the program; SET gets a pointer to CICS’s buffer. After the command the RIDFLD data area can be reused.

WRITE FILE FROM RIDFLD

Adds a record. For a keyed file RIDFLD holds the complete key. A key that already exists gives DUPREC (response 14).

REWRITE FILE FROM

Replaces the record just read with READ UPDATE.

DELETE FILE

Deletes the record read for update (without RIDFLD), or, with RIDFLD (and GENERIC with KEYLENGTH), records by key.

UNLOCK FILE

Releases the lock of a READ UPDATE that the program decides not to follow with a REWRITE or DELETE.

STARTBR FILE RIDFLD

Starts a browse at a position: GTEQ (the default for a KSDS) starts at the first key greater than or equal to the one given, EQUAL needs an exact match, GENERIC with KEYLENGTH a prefix. REQID (default 0) lets one task run several browses at once. No record is read yet.

READNEXT FILE INTO RIDFLD

Reads the next record of the browse; CICS updates RIDFLD with the key of the record read. ENDFILE means the end of the data set was reached. READPREV goes backwards.

RESETBR

Moves the position of a browse without ending it.

ENDBR FILE

Ends the browse and releases its resources. Every successful STARTBR needs one.

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

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.

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 a CALL. COMMAREA(area) LENGTH(n) passes a data area, or CHANNEL('name') a channel. The called program receives the COMMAREA in DFHCOMMAREA (it must use that name) and should test EIBCALEN; IBM recommends keeping the COMMAREA below 24 KB, and warns not to use a LENGTH of 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 a COMMAREA or channel in the same way. It is the way a menu program hands a task over to the program of the chosen option.

  • RETURN ends the program. Without options it gives control back to the caller (or to CICS, ending the task); with TRANSID it 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 RESP and RESP2 options on each command. RESP(data-area) receives the response code of the command and RESP2(data-area) a qualifier, both as halfword or fullword binary items (PIC S9(8) COMP). With RESP present, a condition does not abend the task: control continues with the next statement and the program decides. NOHANDLE also 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

NORMAL

0

The command succeeded.

FILENOTFOUND

12

The file is not defined to CICS.

NOTFND

13

No record has the key.

DUPREC

14

WRITE of a key that exists.

DUPKEY

15

A record reached through a non-unique alternate index has another with the same key after it.

INVREQ

16

The request is invalid; RESP2 says why.

IOERR

17

An I/O error, usually VSAM or hardware.

NOTOPEN

19

The file is closed, quiesced or failed to open.

ENDFILE

20

READNEXT or READPREV reached the end of the browse.

ILLOGIC

21

A VSAM error that fits no other condition; see EIBRCODE.

LENGERR

22

A length is wrong or the data was truncated.

PGMIDERR

27

The program is not defined, disabled or cannot be loaded.

MAPFAIL

36

RECEIVE MAP got no data.

SYSIDERR

53

The remote system is unknown or unavailable.

NOTAUTH

70

A security check failed.

DISABLED

84

The resource is disabled.

CONTAINERERR

110

The container does not exist (GET CONTAINER).

CHANNELERR

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-PARA is the whole control structure of a pseudo-conversational program: EIBCALEN = 0 means the first entry; otherwise the previous COMMAREA is copied from DFHCOMMAREA into working storage and EIBAID chooses the action with EVALUATE. The program ends every non-final path with RETURN TRANSID('CINQ'), so the chain continues. Stacked WHEN clauses (DFHCLEAR and DFHPF3) share one action.

  • DFHCOMMAREA in the LINKAGE SECTION has no storage on the first entry (EIBCALEN is zero), so it is never touched there. The program keeps its own WS-COMM, which is also what it returns: the id of the book on view, six bytes.

  • PROCESS-ENTER tests RESP after RECEIVE MAP. MAPFAIL is an expected outcome and gets a friendly message; any other nonzero response goes to UNEXPECTED-ERROR, which reports RESP and RESP2 on the screen.

  • LOOKUP-BOOK validates the input (BOOKIDL = 0 and BOOKIDI NOT NUMERIC) before it touches the file, because the key field is typed by a person.

  • READ-BOOK handles the file conditions by name: NOTFND is a message to the user, NOTOPEN and DISABLED say the file is not available now, and everything else is unexpected.

  • NEXT-BOOK and READ-NEXT-BOOK show the browse: STARTBR at the id on view with GTEQ, one READNEXT (which returns that same book), a second READNEXT for the next one, and ENDBR in all cases once the browse started; ENDFILE is the "last book" message.

  • SEND-DATA and SHOW-MESSAGE use DATAONLY, so the labels are not resent, and set the length item BOOKIDL to -1 so that the cursor returns to the input field. Only SHOW-MESSAGE uses ALARM.

  • The record layout is the same BOOKREC copybook 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:

  • CICS enables the integrated translator. It can be given in the compiler invocation, on a CBL or PROCESS statement (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. Use NOCICS only if you ran the separate translator first; otherwise the compiler discards the CICS statements it finds.

  • RENT and NODYNAM must be in effect with CICS. The Programming Guide says that specifying DYNAM or NORENT makes the compiler force NODYNAM and RENT. A fix (PTF) of September 2026 allows DYNAM together with CICS, 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 CICS SDFHLOAD library) 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 XOPTS translator option is replaced by the CICS compiler 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.

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 COMMAREA or 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 COMMAREA or a channel.

  • Using COMMAREA fields on the first entry. With EIBCALEN = 0 DFHCOMMAREA has no storage behind it; test EIBCALEN first.

  • Not coding RESP. A program with the default handling abends on NOTFND, MAPFAIL and NOTOPEN, usually with an abend code the user cannot interpret. Not testing it after coding it is worse.

  • Testing EIBAID after RECEIVE MAP. CLEAR and the PA keys send no data and raise MAPFAIL; check the key first.

  • Forgetting ENDBR. A STARTBR without ENDBR keeps the browse (and its resources) until the task ends, and a second STARTBR with the same REQID is an INVREQ.

  • Overwriting RESP before reading it. The next command, including ENDBR, replaces it; save it first.

  • Holding a READ UPDATE across a screen. The lock ends with the task. Re-read and compare before rewriting.

  • Mixing batch and CICS I/O. READ, OPEN, DISPLAY and ACCEPT belong to batch; online programs use EXEC CICS commands.

  • Putting the CICS option in the installation defaults. It changes how every non-CICS program is compiled; give it per program.

  • Sending the whole map every time. DATAONLY keeps the constants on the screen and sends less; use ERASE only when the screen has to be redrawn.

  • Using HANDLE CONDITION in new code. Use RESP and RESP2.

  • Using the numeric value of a response. Test DFHRESP(NOTFND), not 13.