Compiling 64 bit C programs (with MQ) – and using dataset aliases

I wanted to compile one of the MQ samples to run as a 64 bit program. The sample comes compiled as 31 bit.

How did I compile the sample to make it 64 bit?

There is documentation on building 64 bit applications; it provides a compile and link JCL example. However, I wanted to do a compile, bind and go.

//COLINCC JOB 1,MSGCLASS=H
//JOBLIB JCLLIB ORDER=(PP.CBC.ZOS204.SCCNPRC)
//COMPILE EXEC PROC=EDCQCBG,  Needed for 64 bit compile
//   LIBPRFX=CEE,   This is an alias 
//   LNGPRFX=PP.CBC.ZOS204,
//   BPARM='MAP,XREF,RENT,DYNAM=DLL',
//   CPARM='OPTFILE(DD:SYSOPTF)',
//   GPARM='M801 CP0000 1'
//COMPILE.SYSLIB DD DISP=SHR,DSN=&LIBPRFX..SCEEH.SYS.H
//   DD DISP=SHR,DSN=&LIBPRFX..SCEEH.H
//   DD DISP=SHR,DSN=MQM.V900.SCSQC370
//COMPILE.SYSIN DD DISP=SHR,DSN=BETACP.MP1B.JCL(CSQ4BCG1)
//COMPILE.SYS DD DISP=SHR,DSN=&LIBPRFX..SCEEH.SYS.H
//COMPILE.SYSOPTF DD *
WARN 64 RENT LP64 LO SOURCE LIST
NOMARGINS EXPMAC SHOWINC XREF
LANGLVL(EXTENDED) SSCOM DLL
DEFINE(_ALL_SOURCE)
/*
//BIND.SCSQDEFS DD DISP=SHR,DSN=MQM.V900.SCSQDEFS
//BIND.SYSIN DD *  
  INCLUDE SCSQDEFS(CSQBMQ2X)
//GO.STEPLIB   DD DISP=SHR,DSN=MQM.V900.SCSQANLE
//   DD DISP=SHR,DSN=MQM.V900.SCSQLOAD
//   DD DISP=SHR,DSN=MQM.V900.SCSQAUTH

Using ALIASes

The above JCL used

  • an alias (CEE) for some libraries. The CEE alias was defined as SYMBOLIC PP.ADLE370.&SYSLEVEL and RESOLVED PP.ADLE370.ZOS204
  • explicit High Level Qualifier PP.CBC.ZOS204 for other libraries.

If your system provides aliases for data sets, it is better to use the alias, rather than the explicit data set name (or HLQ). When the system is upgraded (to ZOS205), the symbolic will be updated from ZOS204 to ZOS205, the alias will be updated automatically, and any JCL using the alias will still work. If you used the explicit dataset name, when your system is upgraded the dataset may not be available, and you need to update your JCL.

What does an alias point to?

The easiest way I found to see what an alias points to use ISPF 3.4 to list datasets beginning with the alias, for example CEE.SCEEH, and browse it. This browsed dataset was PP.ADLE370.ZOS204.SCEEH, so the alias CEE represents PP.ADLE370.ZOS204.

You can also use a LISTCAT command. (Use ISPF 3.4 and use the I prefix command) and change the command to LISTCAT ENTRIES(CEE.* ) ALL then type EXEC on the command line to execute it.

This gives output like

LISTCAT ENTRIES(CEE.* ) ALL
...
ALIAS --------- CEE.SCEEBIND                                                      
     IN-CAT --- ICFCAT.PLEXH.CATALOG3                                             
     HISTORY                                                                      
       RELEASE----------------2     CREATION--------0000.000                      
     ENCRYPTIONDATA                                                               
       DATA SET ENCRYPTION-----(NO)                                               
     ASSOCIATIONS                                                                 
       SYMBOLIC-PP.ADLE370.&SYSLEVEL..SCEEBIND                                    
       RESOLVED-PP.ADLE370.ZOS204.SCEEBIND                                        

Problems with mqinqmp

I struggled to get MQ in Python to work with Message properties when running on z/OS. I eventually found that mqinqmp() in 64 bit mode was not always working (31 bit mode was fine).

Also the documentation for mqinqmp() is not very clear.

You pass to mqinqmp(), a property name (or a generic like %), a buffer, the size of the buffer, the length of the data, and some other parameters (such as get first, or get next). It returns the property name, the property value ( possibly truncated) , and the true length of the property..

If your buffer is too small to contain all of the property, you get reason code MQRC_PROPERTY_VALUE_TOO_BIG, and should get the true length of the property, its name, type, and length.

This worked fine when it was a 31 bit program. When I ran it as a 64 bit program, it did not return the true length, and did not return the property name.

The documentation says

DataLength Type: MQLONG – output

This is the length in bytes of the actual property value as returned in the Value area.

If DataLength is less than the property value length, DataLength is still filled in on return from the MQINQMP call. This allows the application to determine the size of the buffer required to accommodate the property value, and then reissue the call with a buffer of the appropriate size.

The DataLength is the actual length of the property. (The value returned in the Value area is truncated at Value Length).

What should happen

After you get the MQRC_PROPERTY_VALUE_TOO_BIG reason code, you reallocate the buffer with a size of DataLength and retry the request. It should work the second time.

For me the DataLength was 0, so every time around the loop it got MQRC_PROPERTY_VALUE_TOO_BIG.

What can I use to edit program source in Unix Services on z/OS?

I hit this question trying to edit some Python programs on z/OS in Unix Services.

ISPF services

The easy answer for programs which are in EBCDIC or untagged, is just use ISPF edit, and you can use the HILITE command to highlight the constants and variables in the file. You can use this command to highlite, C, REXX, JCL, XML, assembler etc.

Example output for a C program.

Unfortunately although python supports EBCDIC source files, if you want to compile and package these files, they need to be ASCII files. The Unix Services command OEDIT will detect that the file as an ASCII file, and you can edit it, but not use the HILITE command.

To display the type of the file, use the Unix command ls -Tr *.py . This gave me

t ISO8859-1   T=on  cf.py        
- untagged    T=off aa.py        

Where cf.py is tagged as an ASCII file, an aa.py is an untagged file which defaults to EBCDIC.

Download to your work station

You can download ( FTP) these files to your work station, in binary and edit them. I use gedit on Linux. This has support built in for highlighting source.

IBM developer for z/OS.

This is an eclipse based package which allows you to edit data sets, submit jobs, debug programs etc. It has build in support for C, COBOL etc. When you right click on a file, you can select which editor to use, for example LPEX, a simple editor,a remote C/C++ editor, or an editor on your work station (gedit in my case).

For a python file (*.py), Eclipse downloads the file, and the choice is the eclipse simple text editor, or your workstation standard editor (gedit).

Pydev

Pydev is an Integrate Development Environment for Python on Eclipse (IBM Developer for z/OS). I had a few problems getting it working in Eclipse. (I had to use Pydev 8.2 because of incompatible Java release problem). This provides a Python editor with highlighting, and support for “twisties” where you can hide functions etc. As an editor this worked fine for most of the things I did. There were a couple of surprises.

I could not get the debugger to work, as it tried to debug running the Python program on my laptop – not on z/OS.

Whoops who over wrote my file

With all of the non ISPF techniques there is an integrity problem. If there are two people A and B and they want to edit the file at the same time.
With ISPF and ISPF

  • A edits the file
  • B is prevented from editing the file
  • A saves the updates

If A uses ISPF and B uses IBM developer

  • A edits the file
  • B edits the file
  • A saves the file
  • When B tries to save the file, it detects the last changed time stamp is different, and asks if you want to overwrite it

If A uses ISPF and B uses IBM developer

  • A edits the file
  • B edits the file
  • B saves the file, and as the last changed time stamp has not changed, the save is successful
  • A saves the file, and overwrites the changes B made.

If you use FTP or similar to download the files, there is no locking, and the last person to save will overwrite any previous updates from other people.

Using filters on IBM Developer to limit what is displayed

I was using IBM Developer for z/OS (known as ID/z) to use Eclipse to access files on z/OS, and so use the Eclipse editors and other facilities. The files were displayed in a window, but did not have the handy PF7 and PF8 to scroll through the list. I also had a mixture of python source files, and other files.

I knew there was a way of filtering the displays, but it was a challenge to get this to work.

The easy bit – creating a filter

Under the Remote Systems (Window -> Show view -> Remote systems) it had my connections to z/OS systems, and a tree of my USS files.

On an subdirectory in the tree, right click -> New -> Filter. This gives

  • You can specify (or browse for) a subdirectory
  • You can either filer on file name of file type.

To filter for file type

You cannot type in the file type field. Click on Select… . You can either select from the existing list, or create your own extension. I created .py. This appears in the File types filter box as py, .

If Show files only is unticked, then the filter will displayed the directories below the path you specified as well as any matching files. If this is selected, then only the filtered file names are displayed

When you press Next it prompts you for a name.

When you get back to the Remote systems, window, you should see your filter in the list. If you open the twistie you will see the files you specified.

Changing the filter

This was initially hard because I was not familiar with the Eclipse usage.

Right click on the filter, -> Properties -> Filter Strings and you can change the information in the filter. Click Apply and Close to finish.

Extending the filter

As well as changing a filter, you can add new filter strings. Click on “New filter string”, fill in the details and select “Apply and Close”.

I could not see how to delete a filter once created.

Go into

Although you have filtered the list of files, you have all of the connections, and other displayed information. If you right click a directory, or filter and “go into” you get just that directory or filter output displayed.

Select the folder with an up arrow in it to get back.

Filter pools

You can have a hierarchy of filters, so I could have a set

  • MQ filters – with all of the filter I use for developing MQ applications
  • Python filters – with the filters I use for creating python program, and python unit tests

You can display or hide this through the twistie (menu button) at the top right of the Remote Systems window.

To create a new filter pool, ignore what the documentation says. Where you have “Z/OS UNIX files”, right click on it -> new -> Filter pool.

More information

You can display more information using “Window-> Show view -> Remote Systems -> team”

Using eclipse based tools to z/OS

Eclipse based tools like z/OS Explorer and IBM Developer for z/OS, use a server on the z/OS system called RSED.

This is available on the ZD&T (ZPDT) system, but is hidden away.

You need to mount the file system

mount filesystem(‘FEK320.HALG320.ZFS’) mountpoint(‘/usr/lpp/IBM/zexpl/’)
mode(read)type(ZFS)

Then start the server

s rsed

It’s easy when you know how.

ISPF has autocomplete – just like a laptop!

On Linux I can use “ls D” and tab, and it lists Documents/ and Downloads/ . If I type “ls Doc” and press tab it uses autocomplete to give “ls Documents/”. This is a great way to save you typing.

I’ve just found the same function for z/OS. It has been in the product since at least 2004!

  • Set up a pf key to be AUTOTYPE ( type KEYS on the command line) I set PF6 to this
  • Go to ISPF 3.4 and type the start of a data set, for example COLIN.
  • press PF6, it gives me COLIN.JCL, press PF6 again, it gives me COLIN.MP1B.JCL

Of course you could always type COLIN.* and press enter, then tab down the list. But I thought AUTOTYPE was pretty neat.

Setting PF Keys 13 to 24

When I went to set my PF key, I found all 12 keys were allocated. How do I set keys 13 to 24?
If you use PFSHOW TAILOR it allows you to use 12 or 24 keys, and to control what is displayed.

I have my terminal emulator set up so shift PF5 is PF17, and so I set PF17 to AUTOTYPE.

Easy.

Using point and shoot keys in ISPF

ISPF has had hot keys for many years – I have only just got round to using them.

At the top of ISPF screens there is usually an action bar. For example

   Menu  Utilities  Compilers  Options  Status  Help                       
 ────────────────────────────────────────────────────
                   ISPF Primary Option Menu                           
 Option ===>                                                                   

Where the actions are Menu, Utilities etc. The underlined letter is the hot key for the action.

To select Utilities, type U on the command line and press the “Actions” PF key. This will do the same as tabbing to the Utilities action bar item, and pressing enter. For me PF10 is set to Actions.

You can display your PF Key settings using the keys or pfshow command.

For people who like to use short cuts, have your command line at the top, and use the “home” key. This will get you to the command line. So you can do: home, U, PF10 and quickly get to the Utilities action bar item.

Who develops standard?

When the GUI standards came out I wondered why the standard was to put the command line at the bottom, as there was no “go to command line” key, you had to do “Home”, then shift, tab (to do back tab). This was too many keystrokes for me.

ISPF reflists provide hot lists of datasets and files.

You can set up hot lists of data sets names to make it easier to use data sets and files in Unix Services. For example if your hot list of data sets is SYS1.PROCLIB, ADCD.Z245.PROCLIB, COLIN.PROCLIB, COLIN.C.SOURCE, you can get a list of these in ISPF 3.4 format, so you can quickly move between them, rather than have to keep using ISPF 3.4 and typing in the names of the data sets.

ISPF provides a list called REFLIST with the last 30 datasets or Unix files you referenced, so when you come back from holiday and cannot remember what you were working on, then the REFLIST will show you. Recalling Those Darn Dataset Names is an interesting article.

You can have a hot list of Unix Services files.

You can use the REFLISTD command, or go into ISPF 3.4, up to the action bar, and use the pull down to select REFLIST.
By default, this gives you the a list of the last 30 data sets you used.

Example output

File View Options Help .
────────────────────────────────────────────────────────────────────────────── .
ISRPDSNL Personal Data Set List DSLIST processed .
Command ===> 
Enter a list action to perform or select a data set entry to retrieve. .
Action: S=Save A=Save As D=Delete this list E=Extended Edit L=DSLIST U=UDLIST .
.
Action   Name    Description                  Created Referenced .
L        REFLIST Last 30 referenced data sets         22/04/26 11:45 .

Select Data Set, DSLIST Level or z/OS UNIX file Volume WS 
. 'COLIN.CBT503.FILE967' 
. 'USER.Z24C.CLIST' 
. 'COLIN.SRCHML.LIST' 
. 'COLIN.ZLOGON.CLIST' 
. /u/tmp/zpymqi/code/pymqi/MQMAP.h 
. 'COLIN.CUCI.EXEC' 

The data at the bottom of the display is what is in this list. You cannot do anything with these entries. You can have datasets as well as Unix files in the list

The action only applies to the List entry itself.

If you put an L in front of the REFLIST, you get into standard ISPF 3.4 data set list – with all of the data sets from the list. You can use all of the commands you know and love from this list. You can use option U to list all of the Unix files in the list.

You can also save this list, for example use “A” to create your own list (eg COLIN).

If you want to use this list you can use the command REFACTD COLIN, or go to ISPF 3.4, action bar, REFLIST

1. Current Personal Data Set List (COLIN)
2. List of Personal Data Set Lists

Option 2 gives

ISRPLTAB EFLIST             Personal Data Set Lists                List 1 of 2
Command ===>                                                  Scroll ===> PAGE
                                                                               
Action: O=Open  A=Save As  D=Delete  E=Edit  L=DSLIST  U=UDLIST               
                                                                               
Name      Description                  Created  Referenced
_ COLIN   colin's list                 22/04/26 22/04/26 11:55
_ REFLIST Last 30 referenced data sets          22/04/26 11:57
End

This allows you to pick a list, and specify if you want a data set list, or a Unix file list.

This is really handy – but not very well documented. It feels like it has not been written for the end users but from the IBM developers view point.

Configuring ISPF for new applications.

I found an interesting ISPF extension which I wanted to try out. But I could not find any documentation on how to install it. As usual I found out even more interesting stuff trying to document it.

Logging on to TSO.

When you logon to TSO you specify a procedure such as ISPFPROC. This procedure is in the SYS1.PROCLIB concatenation.  A user can have a default procedure specified in the RACF TSO segment. A user is given access to the RACF CLASS TSOPROC. (So you use a command like RDEFINE TSOPROC NEWPROC UACC(READ) )

This procedure allocates the datasets used by TSO and ISPF, for example ISPPLIB, ISPMLIB, ISPLLIB,ISPEXEC, SYSEXEC, SYSOUT.

If you are authorised you can create your own TSO procedure, and add your application’s data sets to the JCL. Most systems do not allow this.

When this JCL is executed you can pass parameters to it, for example

//ISPFPROC EXEC PGM=IKJEFT01,REGION=0M,DYNAMNBR=200,
//             PARM=’%ISPFCL’                       

will cause the ISPFCL exec or clist to be executed.   This is usually in the SYS1.CLIST concatenation. You can specify PARM=’EXEC ”SYS1.CLIST(SPFALLOC)”’ and specify a data set.

You can use this

  1. To write a message to users
  2. Allocate additional data sets,
  3. Check the existence of a profile, and execute it.

User specific processing

With the clist specified in the PARM statement you can have code like

/* rexx */
address TSO
userid = userid()
zl =”‘”userid”.ZLOGON.CLIST'” /* so we get ‘colin.zlogon.clist’ */
if SYSDSN(zl) = “OK” then exec zlogon /* the userid.. and .clist default’ */

For my userid this would check to see if COLIN.ZLOGON.CLIST exists, and if so, it executes it.

userid.ZLOGON.CLIST

Within this data sets you can have user specific processing, for example

/* Rexx */
say "in colin.zlogon.clist"
address ispexec
"LIBDEF ISPLLIB DATASET ID('COLIN.ISPF.ISPLLIB') STACK"
"LIBDEF ISPMLIB DATASET ID('COLIN.CUCI.ISPMLIB') STACK"
"LIBDEF ISPPLIB DATASET ID('COLIN.CUCI.ISPPLIB') STACK"
"LIBDEF ISPTLIB DATASET ID('COLIN.CUCI.ISPTLIB') STACK"
address tso "ALTLIB ACTIVATE APPLICATION(CLIST)
DATASET('COLIN.CUCI.EXEC') "

This will add the datasets to the specified library, for example adds the panel library COLIN.CUCI.ISPPLIB to ISPPLIB.

You can use “LIBDEF ISPPLIB” to “pop” the definitions back to what they were before the call.

Running your own application

If you have your own panel or application you want to use, you could use the following to set up the libraries and display Mypanel

address ispexec
"LIBDEF ISPLLIB DATASET ID('COLIN.ISPF.ISPLLIB') STACK"
"LIBDEF ISPMLIB DATASET ID('COLIN.CUCI.ISPMLIB') STACK"
"LIBDEF ISPPLIB DATASET ID('COLIN.CUCI.ISPPLIB') STACK"
"LIBDEF ISPTLIB DATASET ID('COLIN.CUCI.ISPTLIB') STACK"
address tso "ALTLIB ACTIVATE APPLICATION(CLIST)
DATASET('COLIN.CUCI.EXEC') "
"SELECT PANEL(Mypanel ) NEWAPPL(MYA) PASSLIB"
/* afterwards reset things back */
address tso "ALTLIB DEACTIVATE APPLICATION(CLIST)"
"LIBDEF ISPLLIB"
"LIBDEF ISPPLIB"
"LIBDEF ISPMLIB"
"LIBDEF ISPTLIB"

What has been libdef-ed?

You can use the TSO command ISPLIBD to display the data sets that have been libdef-ed for the logical screen. Note each logical screen can have its own libdef statements – depending on the set up. See here for a description.

FTP to z/OS when your fingers forget

They say that large dinosaurs had a brain in the head, and a brain near the back legs, because it took too long for information from the feet to reach the brain. I’ve always thought that programmers have a brain in each hands so they can type when the brain is thinking of other things. The problem with this is when you do not use commands, the hand brains forget the commands, and you have to use the head brain. I experienced this trying to FTP a file to z/OS and my fingers would not type the commands I used to know and love!

The FTP daemon needs to be running, for example S FTPD.

FTP to z/OS

  • ftp 10.1.1.2
  • userid ….
  • password

Set up the environment

  • ASCII
  • BIN

Setup the dataset parameters using the site command

site cyl pri=10 sec=10 recfm=fb lrecl=80 blksize=3200 vol=(volid1,volid2)

You can specify size units

  • cyl
  • trk
  • blk

I could not see how to display the default “site” parameters, so if in doubt specify all the parameters.

Change directory ( HLQ) at the remote end

cd ‘COLIN’

Change directory at the local end

lcd /u/colin/

List directories ( HLQ) at the remote end

cd ‘COLIN.CBT’
dir

or

ls ‘COLIN.CBT.*’

Gave

125 List started OK
Volume Unit Referred  Ext Used Recfm Lrecl BlkSz Dsorg Dsname
C4USR1 3390 2022/04/22  1   45    FB    80  5600 PO    V502.FILE967.PDS
250 List completed successfully.

Send files

You can use PUT or GET; MPUT or MGET.

MPUT and MGET will prompt for each file. You can toggle the prompting using the prompt subcommand

prompt
gave
Interactive mode off.

prompt
gave
Interactive mode on.

Additional information

  • ? – displays a summary of the commands
  • help command – gives a short description of the command
  • quit – exit FTP