COUSR01C
Source: cbl/COUSR01C.cbl
Type: CICS transaction program
Purpose
COUSR01C is a CICS transaction (CU01) that implements the "Add User" screen for the CardDemo application's user administration function. It lets an administrator enter a new user's first name, last name, user ID, password, and user type, then adds that user as a record in the USRSEC security file. It provides field-level validation and on-screen feedback (success, duplicate ID, or write failure) before returning control to the calling program or the sign-on screen.
How it works
Processing is driven by MAIN-PARA, which behaves differently depending on how the transaction was invoked:
-
First entry (EIBCALEN = 0): no commarea was passed in, so the program sets the return target to COSGN00C and performs RETURN-TO-PREV-SCREEN to XCTL back out immediately (this looks like a safety/entry guard rather than a normal path).
-
Subsequent entry with commarea: the incoming commarea is copied into CARDDEMO-COMMAREA.
-
If this is the first real display of the screen (NOT CDEMO-PGM-REENTER), the program initializes the output map, sets the cursor to the first-name field, and calls SEND-USRADD-SCREEN to paint the blank Add-User screen.
-
On re-entry (user pressed a key), it calls RECEIVE-USRADD-SCREEN to read the entered data, then branches on EIBAID: ENTER → PROCESS-ENTER-KEY (validate and add the user). PF3 → sets return target to COADM01C and performs RETURN-TO-PREV-SCREEN (back to the admin menu). PF4 → CLEAR-CURRENT-SCREEN (blanks all input fields and redisplays). Any other key → flags an error, resets cursor, shows "invalid key" message, and redisplays via SEND-USRADD-SCREEN.
At the end of every path, MAIN-PARA issues EXEC CICS RETURN with TRANSID(WS-TRANID) and the commarea, keeping the transaction conversational (pseudo-conversational CICS pattern).
PROCESS-ENTER-KEY validates each input field in order — First Name, Last Name, User ID, Password, User Type — and stops at the first blank field found, setting an error flag, positioning the cursor there, and redisplaying the screen with a message. If all required fields are populated, it moves the input values into the SEC-USER-DATA record (SEC-USR-ID, SEC-USR-FNAME, SEC-USR-LNAME, SEC-USR-PWD, SEC-USR-TYPE) and performs WRITE-USER-SEC-FILE.
WRITE-USER-SEC-FILE issues a CICS WRITE to the USRSEC file keyed on SEC-USR-ID, then evaluates the response code: - NORMAL → clears the fields, sets a green success message ("User has been added..."), and redisplays. - DUPKEY/DUPREC → sets an error flag and message "User ID already exist...", repositions cursor to User ID field, and redisplays (user not added). - Any other response → generic "Unable to Add User..." error, cursor reset to First Name, redisplays.
SEND-USRADD-SCREEN always calls POPULATE-HEADER-INFO first (to refresh title, transaction/program name, current date/time in the map header) before sending the BMS map COUSR1A (mapset COUSR01) with the current message text.
CLEAR-CURRENT-SCREEN and INITIALIZE-ALL-FIELDS blank the input fields and message, then redisplay the screen — used for the PF4 "clear" action and also reused internally after a successful add.
Inputs & outputs
No SQL tables are used (parser confirms sql_tables: []) — persistence is entirely through the CICS USRSEC file, not DB2.
Things to know
-
No file-not-found/system-error handling beyond a generic message: WRITE-USER-SEC-FILE's WHEN OTHER branch catches every non-NORMAL, non-duplicate response with a single "Unable to Add User..." message; the actual RESP/REAS codes are only available via a commented-out DISPLAY statement, so diagnosing real failures (e.g., file not open, storage full) requires uncommenting debug code or adding logging.
-
Entry guard oddity: when EIBCALEN = 0, the program immediately routes back to COSGN00C rather than initializing a fresh Add-User screen. This means COUSR01C expects to always be invoked with a populated commarea (e.g., via XCTL from a menu); direct/transaction-only invocation effectively bounces the user to sign-on.
-
Password stored in plain text: SEC-USR-PWD is moved directly from the input field with no masking, hashing, or encryption logic visible in this program.
-
No format/content validation beyond "not empty": fields like USERIDI, PASSWDI, and USRTYPEI are only checked for spaces/low-values — there's no length, character-set, or valid-user-type validation (e.g., no check that user type is a recognized code) before the write.
-
Hard-coded literals: transaction ID 'CU01', program name 'COUSR01C', file name 'USRSEC ', and fallback return program 'COSGN00C' / admin menu 'COADM01C' are all hard-coded in working storage/logic rather than configurable.
-
Duplicate detection relies on file-level key collision: DUPKEY/DUPREC responses from the WRITE are the only mechanism preventing duplicate user IDs — there is no explicit read-before-write existence check in this program.
-
Cursor/error-flag pattern: error handling sets WS-ERR-FLG and moves -1 to the relevant field's length attribute to reposition the BMS cursor, a common CICS/BMS convention but easy to miss if unfamiliar with COBOL/CICS map field naming (xxxxL, xxxxI, xxxxO suffixes for length, input, output).
-
Pseudo-conversational design: because every path ends in EXEC CICS RETURN with a TRANSID, this program relies on CICS pseudo-conversational processing and the CDEMO-PGM-REENTER flag in the commarea to distinguish first display from user response — this is standard CICS practice but a common source of confusion for non-mainframe developers expecting a single continuously-running process.
CICS commands
RETURN, SEND, RECEIVE, WRITE
Copybooks
COCOM01Y, COTTL01Y, COUSR01, CSDAT01Y, CSMSG01Y, CSUSR01Y, DFHAID, DFHBMSCA
Unresolved conditions
Numeric comparisons with no matching 88-level condition-name anywhere in this program or the copybooks it COPYs — no meaning found in the source export, not guessed.
| Field | Value | Line |
|---|---|---|
EIBCALEN |
0 |
78 |
Paragraph flow
flowchart TD
MAIN_PARA["MAIN-PARA"]
PROCESS_ENTER_KEY["PROCESS-ENTER-KEY"]
RETURN_TO_PREV_SCREEN["RETURN-TO-PREV-SCREEN"]
SEND_USRADD_SCREEN["SEND-USRADD-SCREEN"]
RECEIVE_USRADD_SCREEN["RECEIVE-USRADD-SCREEN"]
POPULATE_HEADER_INFO["POPULATE-HEADER-INFO"]
WRITE_USER_SEC_FILE["WRITE-USER-SEC-FILE"]
CLEAR_CURRENT_SCREEN["CLEAR-CURRENT-SCREEN"]
INITIALIZE_ALL_FIELDS["INITIALIZE-ALL-FIELDS"]
CLEAR_CURRENT_SCREEN --> INITIALIZE_ALL_FIELDS
CLEAR_CURRENT_SCREEN --> SEND_USRADD_SCREEN
MAIN_PARA --> CLEAR_CURRENT_SCREEN
MAIN_PARA --> PROCESS_ENTER_KEY
MAIN_PARA --> RECEIVE_USRADD_SCREEN
MAIN_PARA --> RETURN_TO_PREV_SCREEN
MAIN_PARA --> SEND_USRADD_SCREEN
PROCESS_ENTER_KEY --> SEND_USRADD_SCREEN
PROCESS_ENTER_KEY --> WRITE_USER_SEC_FILE
SEND_USRADD_SCREEN --> POPULATE_HEADER_INFO
WRITE_USER_SEC_FILE --> INITIALIZE_ALL_FIELDS
WRITE_USER_SEC_FILE --> SEND_USRADD_SCREEN
Paragraphs
| Paragraph | Line | Performs |
|---|---|---|
| MAIN-PARA | 71 | RETURN-TO-PREV-SCREEN, SEND-USRADD-SCREEN, RECEIVE-USRADD-SCREEN, PROCESS-ENTER-KEY, RETURN-TO-PREV-SCREEN, CLEAR-CURRENT-SCREEN |
| PROCESS-ENTER-KEY | 115 | SEND-USRADD-SCREEN, SEND-USRADD-SCREEN, SEND-USRADD-SCREEN, SEND-USRADD-SCREEN, SEND-USRADD-SCREEN, WRITE-USER-SEC-FILE |
| RETURN-TO-PREV-SCREEN | 165 | |
| SEND-USRADD-SCREEN | 184 | POPULATE-HEADER-INFO |
| RECEIVE-USRADD-SCREEN | 201 | |
| POPULATE-HEADER-INFO | 214 | |
| WRITE-USER-SEC-FILE | 238 | INITIALIZE-ALL-FIELDS, SEND-USRADD-SCREEN, SEND-USRADD-SCREEN, SEND-USRADD-SCREEN |
| CLEAR-CURRENT-SCREEN | 279 | INITIALIZE-ALL-FIELDS, SEND-USRADD-SCREEN |
| INITIALIZE-ALL-FIELDS | 287 |