Some functions in z/OS need a user to be in a privileged state such as key zero or supervisor state. Writing the code in assembler has been pretty easy, but writing it in a C program has been hard.
For example you could write a function in assembler, and call it. This has the cross language challenges.
I recently found an easy way – just reuse some code from Zowe. This is open source, so you need to follow the license
This program and the accompanying materials are made available under the terms of the Eclipse Public License v2.0 which accompanies this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html
SPDX-License-Identifier: EPL-2.0
Copyright Contributors to the Zowe Project.
The code uses __asm() Inline assembly statements (IBM extension).
The functions are
- ddnameExists
- wtoMessage
- wtoPrintf3
- atomicIncrement compare and swap
- testauth
- extractPSW
- supervisorMode or back to problem state
- setKey
- getExternalSecurityManager
- getCVT
- getATCVT
- getIEACSTBL
- getCVTPrefix
- getECVT
- getTCB
- getSTCB
- getOTCB
- getASCB
- getASXB
- getASSB
- getJSAB
- getCurrentACEE
- getFirstChildTCB
- getParentTCB
- getNextSiblingTCB
- resolveSymbolBySyscall Input: A symbol starting with & and not ending with .
- resolveSymbol Input: A symbol starting with & and not ending with .
- lots of saf functions see here
- loadByName
- getDSAB Data Set Association Block
- isCallerLocked
- isCallerCrossMemory
Some of these need to be APF protected, so although it is easy to use the above code, you may still need to get the load library APF authorised, and the code approved.
For example
Get into supervisor state
The code here.
int supervisorMode(int enable){
// Use MODESET macro for requests
int currentPSW = extractPSW();
if (enable){
if (currentPSW & PROBLEM_STATE){
__asm(ASM_PREFIX
" MODESET MODE=SUP \n"
:
:
:"r0","r1","r15");
return TRUE;
} else{
return FALSE; /* do nothing, tell caller no restore needed */
}
} else{
if (currentPSW & PROBLEM_STATE){
return TRUE; /* do nothing, tell user was in problem state */
} else{
__asm(ASM_PREFIX
" MODESET MODE=PROB \n"
:
:
:"r0","r1","r15");
return FALSE;
}
}
}
To compile it I used
// SET LOADLIB=COLIN.LOAD
//DOCLG EXEC PROC=EDCCB,INFILE='ADCD.C.SOURCE(C)',
// CPARM='OPTF(DD:COPTS)'
//* CPARM='LIST,SSCOMM,SOURCE,LANGLVL(EXTENDED)'
//COMPILE.ASMLIB DD DISP=SHR,DSN=SYS1.MACLIB
//COMPILE.COPTS DD *
LIST,SOURCE
aggregate(offsethex) xref
SEARCH(//'ADCD.C.H',//'SYS1.SIEAHDR.H')
TEST
ASM
RENT ILP32 LO
OE
NOMARGINS EXPMAC SHOWINC XREF
LANGLVL(EXTENDED) sscom dll
DEFINE(_ALL_SOURCE)
DEBUG
/*
...
You need to specify
- //COMPILE.ASMLIB for the the assembler macro libraries.
- and the compiler option ASM which enables inlined assembly code inside C/C++ programs.
I was all so easy, once I had been told about it.