diff --git a/c/zos.c b/c/zos.c index da926e628..dbff8b321 100644 --- a/c/zos.c +++ b/c/zos.c @@ -1469,6 +1469,87 @@ int safStat(int options, char *safClass, char *copy, int copyLength, int *racfSt get current TCB AC */ +/* begin WTO SECTION + +TODO(?): This is code duplication from metalio.c but the following works for LE & metal */ + +typedef struct WTO2Common31_tag{ + char replyBufferLength; /* 31-bit WTOR only, else 0 */ + char length; /* message length +4 */ + char mcsFlags1; + char mcsFlags2; +} WTO2Common31; + +void message(char *message){ + + ALLOC_STRUCT31( + STRUCT31_NAME(below2G), + STRUCT31_FIELDS( + WTO2Common31 common; + char text[126]; /* Maximum length of WTO text is 126 - ABEND D23-xxxx0005 if longer than 126 */ + ) + ); + + int len = strlen(message); + if (len>sizeof(below2G->text)) + len=sizeof(below2G->text); + + below2G->common.length = len+sizeof(below2G->common); /* +4 for header */ + memcpy(below2G->text,message,len); + + __asm(ASM_PREFIX + " WTO MF=(E,(%[wtobuf])) \n" + : + :[wtobuf]"NR:r1"(&below2G->common) + :"r0","r1","r15"); + + FREE_STRUCT31( + STRUCT31_NAME(below2G) + ); +} + +#define WTO_MAX_SIZE 126 +void wtoPrintf(char *formatString, ...){ + char text[WTO_MAX_SIZE+1]; /* Allow for trailing null character */ + va_list argPointer; + int cnt; + + for (int pass=0; pass<2; pass++){ + + /* The resulting text string from vsnprintf is unpredictable if + there is an error in the format string or arguments. In that + case we will set the output text area to null, repeat the + vsnprintf, and then find the length of the null terminated + string. This avoids initializing the output text area prior + to every successful request. + */ + + va_start(argPointer,formatString); + cnt = vsnprintf(text,sizeof(text),formatString,argPointer); + va_end(argPointer); + + if (cnt<0){ + if (pass==0) + memset(text,0,sizeof(text)); /* Clear the text buffer before retrying the vsnprint request */ + else { + text[WTO_MAX_SIZE] = 0; /* Ensure strlen stops at the end of the text buffer */ + cnt = strlen(text); /* Find the end of the text string */ + } + } else + break; /* vsnprintf did not return an error - cnt was set */ + } + if (cnt>WTO_MAX_SIZE) /* If more data to format than the text buffer length */ + cnt = WTO_MAX_SIZE; /* Truncate the formatted length to the text buffer length */ + + /* We never want to include a final \n character in the WTO text */ + + if (cnt>0 && text[cnt-1] == '\n') /* If text ends with \n */ + text[cnt-1] = 0; /* Change it into a null character */ + + message(text); +} + +/* end WTO SECTION */ /* LOCATE/CAMLIST */