I was surfing on mqseries.net today and someone asked for help to fix their program that was attempting to send an MQSC command to a z/OS queue manager.
The person had taken someone else’s program that sent a PCF message to a distributed queue manager, twisted and attempted to make it send an MQSC command to a z/OS queue manager. In short, it was garbage. Sorry, but it is.
I have a bunch of programs and code snippets that send an MQSC command to a z/OS queue manager, so I decided to dust-off one and make it available to the world (via this blog).
You can download it as a zip file from here or you can copy from below:
/* * SendCmdTozOS.c is a simple MQ program that will send an MQSC command * to a z/OS queue manager's command queue and then wait for a response. * * Input Parameters: * QMgrName ChlName hostname(port) "MQSC command" * * Where * QMgrName is the queue manager name * ChlName is the name of the channel to be used * hostname(port) is the hostname and port number * "MQSC command" is the MQSC command you want to send to the z/OS queue manager * i.e. * SendCmdTozOS MQT1 TEST.CHL 10.10.10.10(1415) "DIS QL(*)" * * @author Roger Lacroix, Capitalware Inc. * @return 0 for ok or 1 for failed. * @version 1.0.0 * @license Apache 2 License */ #define PROGRAM_NAME "SendCmdTozOS" static const char * EYECATCHER_EyeCatcher = PROGRAM_NAME " "; static const char * EYECATCHER_Version = "1.0.0" ; static const char * EYECATCHER_Datestamp = __DATE__ ; static const char * EYECATCHER_Timestamp = __TIME__ ; static const char * EYECATCHER_Filename = __FILE__ ; #include <stdio.h> #include <stdlib.h> #include <string.h> #include <cmqc.h> #include <cmqxc.h> /* Some basic defines for this program */ #define SYSTEM_MODEL_REPLY_QUEUE "SYSTEM.COMMAND.REPLY.MODEL" #define SYSTEM_COMMAND_INPUT "SYSTEM.COMMAND.INPUT" #define TEMP_DYNAMIC_QUEUE_PREFIX "CSQ.*" #define STR_EQ 0 #define WORK_BUFFER_SIZE 1024 /* Return codes for internal subroutines. */ typedef enum MY_RC_E { RC_OK = 0, RC_WARNING = 4, RC_FAILED = 8, /* */ RC_MAX = 0x7FFFFFFF } MY_RC_T; /* Prototypes */ MY_RC_T ConnectXToQMgr(MQHCONN *, MQLONG *, char *, char *, char *, MQLONG); MY_RC_T DisconnectFromQMgr(MQHCONN *, char *); MY_RC_T OpenDynamicQueue(MQHCONN , MQHOBJ *, char *, char *, char *, char *); MY_RC_T CloseDynamicQueue(MQHCONN , MQHOBJ *, char *); MY_RC_T PutMessage(MQHCONN , char *, char *, char *, char *); MY_RC_T ProcessCmdMessages(MQHCONN , MQHOBJ , char *); /* * ================================================================== * * Function Name * main * * Description * This routine will: * - Connect to a remote z/OS queue manager * - Open a temporary dynamic queue * - Put a message on the queue manager's command queue * - Get a reply message from the temporary dynamic queue * - Close the temporary dynamic queue * - Disconnect from the queue manager * * Input parameters * argc - number of input parameters * **argv - pointer to the array of input parameters * * Return Value * int * ------------------------------------------------------------------ */ int main(int argc, char **argv) { MQHCONN HConn; /* connection handle */ MQHOBJ HReplyQ; /* object handle */ MQLONG ConnectionRC; /* reason code for MQCONN */ char QMgrName[MQ_Q_MGR_NAME_LENGTH+1]; /* z/OS QMgr name */ char channelName[MQ_CHANNEL_NAME_LENGTH+1]; /* z/OS Channel to QMgr */ char hostname[WORK_BUFFER_SIZE+1]; /* z/OS hostname/IP address and port# */ char MQSCCommand[WORK_BUFFER_SIZE+1]; /* MQSC command the user wishes to have executed */ char ResolvedQName[MQ_Q_NAME_LENGTH+1]; if (argc != 5) { printf("%s QMgrName ChlName hostname(port) \"MQSC command\"\n", PROGRAM_NAME); return(1); } printf("%s v%s starting\n", PROGRAM_NAME, EYECATCHER_Version); strncpy(QMgrName, argv[1], MQ_Q_MGR_NAME_LENGTH); QMgrName[MQ_Q_MGR_NAME_LENGTH] = 0x00; strncpy(channelName, argv[2], MQ_CHANNEL_NAME_LENGTH); channelName[MQ_CHANNEL_NAME_LENGTH] = 0x00; strncpy(hostname, argv[3], WORK_BUFFER_SIZE); hostname[WORK_BUFFER_SIZE] = 0x00; strncpy(MQSCCommand, argv[4], WORK_BUFFER_SIZE); MQSCCommand[WORK_BUFFER_SIZE] = 0x00; printf("Using values:\n"); printf(" QMgrName : %s\n", QMgrName); printf(" hostname : %s\n", hostname); printf(" channelName : %s\n", channelName); printf(" MQSC command: %s\n", MQSCCommand); if (RC_OK == ConnectXToQMgr(&HConn, &ConnectionRC, QMgrName, hostname, channelName, MQCNO_NONE)) { /* Open the Dynamic Input Q */ if (RC_OK == OpenDynamicQueue(HConn, &HReplyQ, ResolvedQName, QMgrName, SYSTEM_MODEL_REPLY_QUEUE, TEMP_DYNAMIC_QUEUE_PREFIX)) { /* Put the MQSC command on the queue manager's command queue */ if (RC_OK == PutMessage(HConn, QMgrName, SYSTEM_COMMAND_INPUT, ResolvedQName, MQSCCommand)) { ProcessCmdMessages(HConn, HReplyQ, ResolvedQName); } CloseDynamicQueue(HConn, &HReplyQ, ResolvedQName); } /* Disconnect from the queue manager */ if (ConnectionRC != MQRC_ALREADY_CONNECTED) { DisconnectFromQMgr(&HConn, QMgrName); } } printf("%s ending.\n", PROGRAM_NAME); return(0); } /* * ================================================================== * * Function Name * ConnectXToQMgr * * Description * This routine will establish a connection between * this application and a remote queue manager. * * Input parameters * *Hconn - pointer to the conn. handle returned from MQCONN * *connectRC - pointer to the RC returned from MQCONN * QMgrName - Queue Manager name * *hostname - hostname/IP address and port # * *channelName - channel name to qeue manager * Options - connection options * * Output * *Hconn - pointer to the conn. handle returned from MQCONN * *connectRC - pointer to the RC returned from MQCONN * * Return Value * MY_RC_T * ------------------------------------------------------------------ */ MY_RC_T ConnectXToQMgr(MQHCONN *Hconn, MQLONG *connectRC, char *QMgrName, char *hostname, char *channelName, MQLONG Options) { /* -------------------------------------------- * Variable declarations. * -------------------------------------------- */ MY_RC_T rcode = RC_OK; MQLONG mqCC; /* completion code from QMgr */ MQCD ClientConn = {MQCD_CLIENT_CONN_DEFAULT}; /* Client connection channel */ MQCNO cno = {MQCNO_DEFAULT}; /* Connect Options */ /* -------------------------------------------- * Code section * -------------------------------------------- */ strncpy(ClientConn.ConnectionName, hostname, MQ_CONN_NAME_LENGTH); strncpy(ClientConn.ChannelName, channelName, MQ_CHANNEL_NAME_LENGTH); /* Point the MQCNO to the client connection definition */ cno.ClientConnPtr = &ClientConn; cno.Version = MQCNO_VERSION_2; cno.Options = Options; MQCONNX( QMgrName, /* queue manager */ &cno, /* connection options */ Hconn, /* connection handle */ &mqCC, /* completion code */ connectRC); /* reason code */ printf("MQConn CC=%d RC=%d on connection to %s\n", mqCC, *connectRC, QMgrName ); if (mqCC == MQCC_FAILED) rcode = RC_FAILED; else rcode = RC_OK; return (rcode); } /* * ================================================================== * * Function Name * DisconnectFromQMgr * * Description * This routine will sever an existing connection between this * application and the queue manager. * * Input parameters * *Hconn - pointer to the conn. handle returned from MQCONN * QMgrName - Queue Manager name * * Output * *Hconn - pointer to the conn. handle returned from MQCONN * * Return Value * MY_RC_T * ------------------------------------------------------------------ */ MY_RC_T DisconnectFromQMgr(MQHCONN *Hconn, char *QMgrName) { /* -------------------------------------------- * Variable declarations. * -------------------------------------------- */ MY_RC_T rcode = RC_OK; MQLONG mqCC; /* completion code from QMgr */ MQLONG mqRC; /* reason code from QMgr */ /* -------------------------------------------- * Code section * ------------------------------------- ------- */ MQDISC( Hconn, /* connection handle */ &mqCC, /* completion code */ &mqRC); /* reason code */ printf("MQDisc CC=%d RC=%d on disconnecting from %s\n", mqCC, mqRC, QMgrName ); if (mqCC == MQCC_FAILED) rcode = RC_FAILED; else rcode = RC_OK; return (rcode); } /* * ================================================================== * * Function Name * OpenDynamicQueue * * Description * This routine will create and open the temporary dynamic input queue. * * Input parameters * Hconn - connection handle * *HObj - pointer to the object handle returned from MQOPEN * *ResolvedQName - pointer to object name returned from MQOPEN * QMgrName - Queue Manager name * ModelQName - Model Q name * DynQName - Dynamic Q name * * Output * *ResolvedQName - pointer to object name returned from MQOPEN * * Return Value * MY_RC_T * ------------------------------------------------------------------ */ MY_RC_T OpenDynamicQueue(MQHCONN Hconn, MQHOBJ *HObj, char *ResolvedQName, char *QMgrName, char *ModelQName, char *DynQName) { /* -------------------------------------------- * Variable declarations. * -------------------------------------------- */ MY_RC_T rcode = RC_OK; MQLONG mqCC; /* completion code from QMgr */ MQLONG mqRC; /* reason code from QMgr */ MQOD od = {MQOD_DEFAULT}; MQLONG OpenOptions = MQOO_FAIL_IF_QUIESCING | MQOO_INPUT_SHARED; /* -------------------------------------------- * Code section * -------------------------------------------- */ strcpy( od.ObjectQMgrName, QMgrName); strcpy(od.ObjectName, ModelQName); strcpy(od.DynamicQName, DynQName); MQOPEN( Hconn, /* connection handle */ &od, /* object descriptor */ OpenOptions, /* open options */ HObj, /* object handle */ &mqCC, /* completion code */ &mqRC); /* reason code */ printf("MQOpen CC=%d RC=%d for %s\n", mqCC, mqRC, DynQName ); if ( mqCC == MQCC_OK ) { strncpy(ResolvedQName, od.ObjectName, MQ_Q_NAME_LENGTH); ResolvedQName[MQ_Q_NAME_LENGTH] = 0x00; printf("Dynamic Queue Name: %s\n", ResolvedQName ); rcode = RC_OK; } else { rcode = RC_FAILED; } return (rcode); } /* * ================================================================== * * Function Name * CloseDynamicQueue * * Description * This routine will close and delete the temporary dynamic queue. * * Input parameters * Hconn - connection handle * *HObj - pointer to the object handle * *QName - pointer to Q name * * Output * *HObj - pointer to the object handle * * Return Value * MY_RC_T * ------------------------------------------------------------------ */ MY_RC_T CloseDynamicQueue(MQHCONN Hconn, MQHOBJ *HObj, char *QName) { /* -------------------------------------------- * Variable declarations. * -------------------------------------------- */ MY_RC_T rcode = RC_OK; MQLONG mqCC; /* completion code from QMgr */ MQLONG mqRC; /* reason code from QMgr */ MQLONG CloseOptions = MQCO_DELETE_PURGE; /* delete the queue and any messages */ /* -------------------------------------------- * Code section * -------------------------------------------- */ MQCLOSE( Hconn, HObj, CloseOptions, &mqCC, &mqRC); printf("MQClose CC=%d RC=%d for %s\n", mqCC, mqRC, QName); if (mqCC == MQCC_FAILED) rcode = RC_FAILED; else rcode = RC_OK; return (rcode); } /* * ================================================================== * * Function Name * PutMessage * * Description * This routine will put a message on a queue. * * Input parameters * Hconn - connection handle * QMgrName - pointer to Queue Manager name * QMgrName - pointer to Queue name * ReplyQName - pointer to Reply Q name * messageData - pointer to message data * * Output * None. * * Return Value * MY_RC_T * ------------------------------------------------------------------ */ MY_RC_T PutMessage(MQHCONN Hconn, char *QMgrName, char *QName, char *ReplyQName, char *messageData) { /* -------------------------------------------- * Variable declarations. * -------------------------------------------- */ MY_RC_T rcode = RC_OK; MQLONG mqCC; /* completion code from QMgr */ MQLONG mqRC; /* reason code from QMgr */ MQOD od = {MQOD_DEFAULT}; /* Object Descriptor */ MQMD md = {MQMD_DEFAULT}; /* Message Descriptor */ MQPMO pmo = {MQPMO_DEFAULT}; /* put message options */ /* -------------------------------------------- * Code section * -------------------------------------------- */ /* Set OPEN options */ strncpy(od.ObjectQMgrName, QMgrName, MQ_Q_MGR_NAME_LENGTH); strncpy(od.ObjectName, QName, MQ_Q_NAME_LENGTH); /* Set MQPUT options */ pmo.Options = MQPMO_FAIL_IF_QUIESCING | MQPMO_NO_SYNCPOINT; /* Setup Message Descriptor */ md.MsgType = MQMT_REQUEST; md.Expiry = MQEI_UNLIMITED; md.Feedback = MQFB_NONE; md.Encoding = MQENC_NATIVE; md.Priority = MQPRI_PRIORITY_AS_Q_DEF; md.Persistence = MQPER_PERSISTENCE_AS_Q_DEF; memcpy(md.MsgId, MQMI_NONE, sizeof(md.MsgId) ); memcpy(md.CorrelId, MQCI_NONE, sizeof(md.CorrelId) ); memcpy(md.GroupId, MQGI_NONE, sizeof(md.GroupId)); memcpy(md.Format, MQFMT_STRING, sizeof(md.Format) ); strncpy(md.ReplyToQ, ReplyQName, MQ_Q_NAME_LENGTH ); MQPUT1(Hconn, /* connection handle */ &od, /* object descriptor */ &md, /* message descriptor */ &pmo, /* put message options */ strlen(messageData),/* buffer length */ messageData, /* message buffer */ &mqCC, /* completion code */ &mqRC); /* reason code */ printf("MQPUT1 CC=%d RC=%d for %s\n", mqCC, mqRC, QName ); if (mqCC == MQCC_FAILED) rcode = RC_FAILED; else rcode = RC_OK; return (rcode); } /* * ================================================================== * * Function Name * ProcessCmdMessages * * Description * This routine will get all reply messages from our temporary * dynamic queue. * * Input parameters * Hconn - connection handle * HObj - Object handle for reply Q * QName - reply queue name * * Output * Response messages will be written to stdout * * Return Value * MY_RC_T * ------------------------------------------------------------------ */ MY_RC_T ProcessCmdMessages(MQHCONN Hconn, MQHOBJ HObj, char *QName) { /* -------------------------------------------- * Variable declarations. * -------------------------------------------- */ MY_RC_T rcode = RC_OK; MQLONG mqCC; /* completion code from QMgr */ MQLONG mqRC; /* reason code from QMgr */ MQLONG bufLen = 0; /* length of the buffer */ MQLONG msgLen = 0; /* length of the return message */ MQMD md = {MQMD_DEFAULT}; MQGMO gmo = {MQGMO_DEFAULT}; char Continue = 'Y'; char ResponseBuffer[WORK_BUFFER_SIZE+1]; /* way too big but that is ok! */ /* -------------------------------------------- * Code section * -------------------------------------------- */ gmo.Options = MQGMO_FAIL_IF_QUIESCING | MQGMO_CONVERT | MQGMO_WAIT | MQGMO_NO_SYNCPOINT; gmo.WaitInterval = 5 * 1000; /* wait up to 5 seconds */ /* * Loop through the messages on the queue. */ while ( Continue == 'Y' ) { bufLen = WORK_BUFFER_SIZE; memcpy(md.MsgId, MQMI_NONE, sizeof(md.MsgId)); memcpy(md.CorrelId, MQCI_NONE, sizeof(md.CorrelId)); memcpy(md.Format, MQFMT_NONE, (size_t)MQ_FORMAT_LENGTH); MQGET(Hconn, /* connection handle */ HObj, /* object handle */ &md, /* message descriptor */ &gmo, /* get message options */ bufLen, /* buffer length */ ResponseBuffer, /* message buffer */ &msgLen, /* message length */ &mqCC, /* completion code */ &mqRC); /* reason code */ if ( mqCC == MQCC_OK ) { ResponseBuffer[msgLen] = 0x00; /* add a null */ printf("Response: %s\n", ResponseBuffer); if (memcmp(ResponseBuffer,"CSQ9022I",8) == STR_EQ) Continue = 'N'; /* no more messages to follow */ } else if ( (mqCC != MQCC_OK) && (mqRC == MQRC_NO_MSG_AVAILABLE) ) { /* No more messages on the queue. */ Continue = 'N'; } else { printf("MQGET CC=%d RC=%d for %s\n", mqCC, mqRC, QName ); rcode = RC_FAILED; Continue = 'N'; } } /* while ( Continue == 'Y' ) */ return (rcode); }
Regards,
Roger Lacroix
Capitalware Inc.
2 Responses to C Program to Send an MQSC Command to a z/OS Queue Manager