Ejemplo n.º 1
0
/*====================================================================*/
int formatResponsePart(
                 Message* pRequestMessage,
                 Message* pResponseMessage) {


    if (g_pTraceParms->traceMode == TRUE_CODE) {
       traceMessage(MODULE_NAME, "Entered formatResponsePart");
    }
    /* Format the single output message part. It has the
     * content as the input message part since the linked program
     * updated the content.  */
    memset(pResponseMessage->pParts->ID, ' ', MSG_ID_LEN);
    memcpy(pResponseMessage->pParts->ID, COMMAREA_PART_ID,
           sizeof(COMMAREA_PART_ID) - 1);
    pResponseMessage->pParts->size.as_int =
           pRequestMessage->pParts->size.as_int;
    pResponseMessage->pParts->content =
           pRequestMessage->pParts->content;
    adjustPartSize(pResponseMessage->pParts);

    /* In order to avoid having 2 pointers on the same memory location
     * which would complicate freeing memory, we disconnect the
     * input message from its content. */
    pRequestMessage->pParts->size.as_int = 0;
    pRequestMessage->pParts->content = NULL;

    if (g_pTraceParms->traceMode == TRUE_CODE) {
       traceMessage(MODULE_NAME, "Return from formatResponsePart");
    }
    return OK_CODE;
}
Ejemplo n.º 2
0
/*====================================================================*/
int parseKeyValues(int keyValuesSize,
                   void* keyValues,
                   CICSProgramDesc* pProgramDesc) {

    char* remaining;
    char key[MAX_KEY_LEN];
    char value[MAX_VALUE_LEN];
    int rc = OK_CODE;

    if (g_pTraceParms->traceMode == TRUE_CODE) {
       traceMessage(MODULE_NAME, "Entered parseKeyValues");
    }

    /* We expect the first token encountered to be a key */
    remaining = getToken(
                    keyValues, key, MAX_KEY_LEN - 1,
                    KEYWORD_DELIM, KEYWORD_DELIM);
    while (rc == OK_CODE
           && key != NULL
           && strlen(key) > 0
           && remaining != NULL) {

        /*  Values are separated from keys by a column char */
        remaining = getValueStart(remaining);
        if (remaining != NULL) {
            switch(remaining[0]) {
               /* Case of a simple value "key":"value" */
               case VALUE_DELIM:
                  remaining = getToken(
                                 remaining, value, MAX_VALUE_LEN - 1,
                                 VALUE_DELIM, VALUE_DELIM);
                  rc = processKeyValue(key, value, pProgramDesc);
                  break;
               /* Case of an array "key":["value1",.,"valuen"]*/
               case ARRAY_START_DELIM:
                  remaining = getToken(
                                 remaining, value, MAX_VALUE_LEN - 1,
                                 ARRAY_START_DELIM, ARRAY_END_DELIM);
                  rc = processKeyArray(key, value, pProgramDesc);
                  break;
            }
            /* Look for the next key */
            remaining = getToken(remaining, key, MAX_KEY_LEN - 1,
                                 KEYWORD_DELIM, KEYWORD_DELIM);
        }
    }

    if (g_pTraceParms->traceMode == TRUE_CODE) {
        traceProgramDesc(pProgramDesc);
        traceMessage(MODULE_NAME, "Ended parseKeyValues");
    }

    return rc;
}
Ejemplo n.º 3
0
/*====================================================================*/
int checkCommarea(CICSProgramDesc* pProgramDesc,
                  Message* pRequestMessage) {

    HeaderPartContent* pRequestHeaderPartContent
         = (HeaderPartContent*) pRequestMessage->pHeaderPart->content;
    MessagePart* pInputPart = pRequestMessage->pParts;
    int inPartsNum = pRequestHeaderPartContent->partsNumber.as_int;

    if (g_pTraceParms->traceMode == TRUE_CODE) {
       traceMessage(MODULE_NAME, "Entered checkCommarea");
    }
    /* We need a program name; We don't perform an inquire on the
     * program because that fails with autoinstall. */
    if (strlen(pProgramDesc->CICSProgram) == 0) {
        logError(MODULE_NAME, "No CICS program name was provided.");
        return ERROR_CODE;
    }

    /* There must be one, and only one, input message part. */
    if (inPartsNum == 0) {
        logError(MODULE_NAME, "No input message part for commarea.");
        return ERROR_CODE;
    }
    if (inPartsNum > 1) {
        logError(MODULE_NAME, "Too many message parts for commarea.");
        return ERROR_CODE;
    }

    /* If no commarea length was specified, assume the size of the
     * incoming data. */
    if (pProgramDesc->CICSLength == 0) {
        pProgramDesc->CICSLength = pInputPart->size.as_int;
    }

    /* If DataLength is specified, it must be smaller than the
     * commarea length. */
    if (pProgramDesc->CICSDataLength > pProgramDesc->CICSLength) {
        logError(MODULE_NAME,
                   "Data length cannot exceed commarea length.");
        return ERROR_CODE;
    }

    /* If no data length was specified, assume the size of the
     * incoming data. */
    if (pProgramDesc->CICSDataLength == 0) {
        pProgramDesc->CICSDataLength = pInputPart->size.as_int;
    }

    if (g_pTraceParms->traceMode == TRUE_CODE) {
       traceMessage(MODULE_NAME, "Return from checkCommarea");
    }
    return OK_CODE;
}
Ejemplo n.º 4
0
/*====================================================================*/
int invokeProgram(DFHEIBLK *inDfheiptr,
                  TraceParms* inTraceParms,
                  CICSProgramDesc* pProgramDesc,
                  Message* pRequestMessage,
                  Message* pResponseMessage) {

    int rc;
    HeaderPartContent* pRequestHeaderPartContent
         = (HeaderPartContent*) pRequestMessage->pHeaderPart->content;

    dfheiptr = inDfheiptr;
    g_pTraceParms = inTraceParms;
    initLog(dfheiptr, inTraceParms);
    initProgramDesc(pProgramDesc);

    if (g_pTraceParms->traceMode == TRUE_CODE) {
       traceMessage(MODULE_NAME, "About to invoke program");
    }

    /* Parse the request header key/value pairs */
    rc = parseKeyValues(
                pRequestHeaderPartContent->keyValuesSize.as_int,
                pRequestHeaderPartContent + 1,
                pProgramDesc);
    /* Link to the target program */
    if (OK_CODE == rc) {
        if (strlen(pProgramDesc->CICSChannel) > 0
            && pProgramDesc->CICSChannel[0] != ' ') {
            rc = linkChannel(dfheiptr,
                             g_pTraceParms,
                             pProgramDesc,
                             pRequestMessage,
                             pResponseMessage);
        } else {
            rc = linkCommarea(dfheiptr,
                              g_pTraceParms,
                              pProgramDesc,
                              pRequestMessage,
                              pResponseMessage);
        }
    }

    if (g_pTraceParms->traceMode == TRUE_CODE) {
       if (ERROR_CODE == rc) {
           traceMessage(MODULE_NAME, "Invoke program failed");
       } else {
           traceMessage(MODULE_NAME, "Return from invoke program");
       }
    }

    return rc;
}
Ejemplo n.º 5
0
/*====================================================================*/
int freeMessage(Message* pMessage) {

    int i = 0;
    int partsNumber = 0;
    HeaderPartContent* pHeaderPartContent =
          (HeaderPartContent*)pMessage->pHeaderPart->content;
    MessagePart* part;

    if (pHeaderPartContent != NULL) {

      partsNumber = pHeaderPartContent->partsNumber.as_int;

      /* Free the header part content */
      EXEC CICS FREEMAIN
                DATAPOINTER(pHeaderPartContent)
                RESP(g_cicsResp) RESP2(g_cicsResp2);
      if (g_cicsResp != DFHRESP(NORMAL)) {
         logCicsError(MODULE_NAME, "FREEMAIN",
                        g_cicsResp, g_cicsResp2);
         return ERROR_CODE;
      }
      if (g_pTraceParms->traceMode == TRUE_CODE) {
         sprintf(g_traceMessage,
          "Header part content freed from %#x",
          (int)pHeaderPartContent);
          traceMessage(MODULE_NAME, g_traceMessage);
      }

      /* Now free the message parts content */
      for (i = 0; i < partsNumber && i < MAX_IN_MSG_PARTS; i++) {
          part = pMessage->pParts + i;
          if (part->content != NULL) {
            EXEC CICS FREEMAIN
                      DATAPOINTER(part->content)
                      RESP(g_cicsResp) RESP2(g_cicsResp2);
            if (g_cicsResp != DFHRESP(NORMAL)) {
               logCicsError(MODULE_NAME, "FREEMAIN",
                                  g_cicsResp, g_cicsResp2);
               return ERROR_CODE;
            }
            if (g_pTraceParms->traceMode == TRUE_CODE) {
               sprintf(g_traceMessage,
                "Message part content freed from %#x",
                (int)part->content);
                traceMessage(MODULE_NAME, g_traceMessage);
            }
          }
      }
    }

    return OK_CODE;
}
Ejemplo n.º 6
0
/*====================================================================*/
int reallocContent(CICSProgramDesc* pProgramDesc,
                   MessagePart* pInputPart) {

    char* newContent;

    if (g_pTraceParms->traceMode == TRUE_CODE) {
       traceMessage(MODULE_NAME, "Reallocating content");
    }
    EXEC CICS GETMAIN
              SET(newContent)
              INITIMG('\0')
              FLENGTH(pProgramDesc->CICSLength + 1)
              RESP(g_cicsResp) RESP2(g_cicsResp2);

    if (g_cicsResp != DFHRESP(NORMAL)) {
       logCicsError(MODULE_NAME, "GETMAIN",
                     g_cicsResp, g_cicsResp2);
       return ERROR_CODE;
    }
    memcpy(newContent, pInputPart->content, pInputPart->size.as_int);
    if (pInputPart->content != NULL) {
        EXEC CICS FREEMAIN
                  DATAPOINTER(pInputPart->content)
                  RESP(g_cicsResp) RESP2(g_cicsResp2);
        if (g_cicsResp != DFHRESP(NORMAL)) {
           logCicsError(MODULE_NAME, "FREEMAIN",
                        g_cicsResp, g_cicsResp2);
           return ERROR_CODE;
        }
    }

    if (g_pTraceParms->traceMode == TRUE_CODE) {
       sprintf(g_traceMessage,
        "Content reallocated from %#x size=%d to %#x size=%ld",
        (int)pInputPart->content,
        pInputPart->size.as_int,
        (int)newContent,
        pProgramDesc->CICSLength);
        traceMessage(MODULE_NAME, g_traceMessage);
    }
    /* Update the input part to reflect the new allocation */
    pInputPart->content = newContent;
    pInputPart->size.as_int = pProgramDesc->CICSLength;

    return OK_CODE;
}
Ejemplo n.º 7
0
/*====================================================================*/
int formatResponseHeader(
                 Message* pResponseMessage) {

    /* Format header part, indicating  no key/values.  */
    int headerLength = PARTS_NUM_LEN + KEYVAL_SIZE_LEN;
    HeaderPartContent* pResponseHeaderPartContent;

    if (g_pTraceParms->traceMode == TRUE_CODE) {
       traceMessage(MODULE_NAME, "Entered formatResponseHeader");
    }

    memset(pResponseMessage->pHeaderPart->ID, ' ', MSG_ID_LEN);
    memcpy(pResponseMessage->pHeaderPart->ID, HEADER_PART_ID,
           sizeof(HEADER_PART_ID) - 1);
    pResponseMessage->pHeaderPart->size.as_int = headerLength;

    EXEC CICS GETMAIN
              SET(pResponseMessage->pHeaderPart->content)
              INITIMG('\0')
              FLENGTH(headerLength)
              RESP(g_cicsResp) RESP2(g_cicsResp2);

    if (g_cicsResp != DFHRESP(NORMAL)) {
       logCicsError(MODULE_NAME, "GETMAIN",
                     g_cicsResp, g_cicsResp2);
       return ERROR_CODE;
    }
    if (g_pTraceParms->traceMode == TRUE_CODE) {
       sprintf(g_traceMessage,
        "Response header part content allocated at %#x size=%d",
        (int)pResponseMessage->pHeaderPart->content, headerLength);
        traceMessage(MODULE_NAME, g_traceMessage);
    }
    pResponseHeaderPartContent
         = (HeaderPartContent*) pResponseMessage->pHeaderPart->content;
    pResponseHeaderPartContent->partsNumber.as_int = 1;
    pResponseHeaderPartContent->keyValuesSize.as_int = 0;

    if (g_pTraceParms->traceMode == TRUE_CODE) {
       traceMessage(MODULE_NAME, "Return from formatResponseHeader");
    }
    return OK_CODE;
}
Ejemplo n.º 8
0
int sendAuthentificationAnswer(Connection *connection, Buffer *send_buffer, char answer_type)
{
	if(answer_type != REJECT_AUTHENTIFICATION && answer_type != ACCEPT_AUTHENTIFICATION)
		return -1;
	GenericPacket packet;
	packet.data = NULL;
	packet.data_length = 0;
	packet.type = answer_type;
	traceMessage("Authentication packet will be sent");
	return sendPacket(connection, &packet, send_buffer);
}
Ejemplo n.º 9
0
/*====================================================================*/
int traceProgramDesc(CICSProgramDesc* pProgramDesc) {
    int i;
    char outContainerName[CONTAINER_NAME_LEN + 1];
    int pos = 0;

    sprintf(g_traceMessage,
        "CICSProgram=%s", pProgramDesc->CICSProgram);
    traceMessage(MODULE_NAME, g_traceMessage);
    sprintf(g_traceMessage,
        "CICSLength=%ld", pProgramDesc->CICSLength);
    traceMessage(MODULE_NAME, g_traceMessage);
    sprintf(g_traceMessage,
        "CICSDataLength=%ld", pProgramDesc->CICSDataLength);
    traceMessage(MODULE_NAME, g_traceMessage);
    sprintf(g_traceMessage,
        "CICSSysID=%s", pProgramDesc->CICSSysID);
    traceMessage(MODULE_NAME, g_traceMessage);
    sprintf(g_traceMessage,
        "CICSSyncOnReturn=%ld", pProgramDesc->CICSSyncOnReturn);
    traceMessage(MODULE_NAME, g_traceMessage);
    sprintf(g_traceMessage,
        "CICSTransID=%s", pProgramDesc->CICSTransID);
    traceMessage(MODULE_NAME, g_traceMessage);
    sprintf(g_traceMessage,
        "CICSChannel=%s", pProgramDesc->CICSChannel);
    traceMessage(MODULE_NAME, g_traceMessage);
    sprintf(g_traceMessage,
        "CICSOutputContainersCount=%d",
         pProgramDesc->CICSOutputContainersCount);
    traceMessage(MODULE_NAME, g_traceMessage);

    for (i=0; i < pProgramDesc->CICSOutputContainersCount; i++) {
        memset(outContainerName, '\0', CONTAINER_NAME_LEN + 1);
        memcpy(outContainerName,
           pProgramDesc->CICSOutputContainers + pos,
           CONTAINER_NAME_LEN);
        sprintf(g_traceMessage,
            "CICSOutContainer=%s", outContainerName);
        traceMessage(MODULE_NAME, g_traceMessage);
        pos += (CONTAINER_NAME_LEN + 1);
    }
    return OK_CODE;
}
Ejemplo n.º 10
0
/*====================================================================*/
int formatCommareaResponse(CICSProgramDesc* pProgramDesc,
                          Message* pRequestMessage,
                          Message* pResponseMessage) {


    if (g_pTraceParms->traceMode == TRUE_CODE) {
       traceMessage(MODULE_NAME, "Entered formatCommareaResponse");
    }

    if (OK_CODE != formatResponseHeader(pResponseMessage)) {
        return ERROR_CODE;
    }

     if (OK_CODE != formatResponsePart(
                      pRequestMessage, pResponseMessage)) {
         return ERROR_CODE;
     }

    if (g_pTraceParms->traceMode == TRUE_CODE) {
       traceMessage(MODULE_NAME, "Return from formatCommareaResponse");
    }
    return OK_CODE;
}
Ejemplo n.º 11
0
/*====================================================================*/
int freeCommarea(DFHEIBLK *inDfheiptr,
                TraceParms* inTraceParms,
                CICSProgramDesc* pProgramDesc,
                Message* pRequestMessage,
                Message* pResponseMessage) {

    int rc = OK_CODE;

    dfheiptr = inDfheiptr;
    g_pTraceParms = inTraceParms;
    initLog(dfheiptr, inTraceParms);

    if (g_pTraceParms->traceMode == TRUE_CODE) {
       traceMessage(MODULE_NAME, "Entered freeCommarea");
    }

    rc = freeMessage(pRequestMessage);
    rc = freeMessage(pResponseMessage);

    if (g_pTraceParms->traceMode == TRUE_CODE) {
       traceMessage(MODULE_NAME, "Return from freeCommarea");
    }
    return rc;
}
Ejemplo n.º 12
0
/*====================================================================*/
int adjustPartSize(MessagePart* pPart) {
    int i = 0;
    int lastNonNull = -1;
    for (i = 0; i < pPart->size.as_int; i++) {
        if (pPart->content[i] != '\0') {
            lastNonNull = i;
        }
    }
    if (g_pTraceParms->traceMode == TRUE_CODE) {
       sprintf(g_traceMessage,
        "Response content size reduced from %d to %d",
        pPart->size.as_int,
        lastNonNull + 1);
        traceMessage(MODULE_NAME, g_traceMessage);
    }
    pPart->size.as_int = lastNonNull + 1;
    return OK_CODE;
}
Ejemplo n.º 13
0
/*====================================================================*/
int processKeyValue(char* key,
                    char* value,
                    CICSProgramDesc* pProgramDesc) {

    if (value == NULL || strlen(value) == 0) {
        logError(MODULE_NAME, "Key found with no associated value.");
        return ERROR_CODE;
    }

    if (g_pTraceParms->traceMode == TRUE_CODE) {
        sprintf(g_traceMessage,
            "processKeyValue key=%s value=%s", key, value);
        traceMessage(MODULE_NAME, g_traceMessage);
    }

    if (0 == strcmp(PROGRAM_KEY, key)) {
        memset(pProgramDesc->CICSProgram, ' ', PROGNAME_LEN);
        memcpy(pProgramDesc->CICSProgram, value, strlen(value));
    } else {
    if (0 == strcmp(LENGTH_KEY, key)) {
        pProgramDesc->CICSLength = atol(value);
    } else {
    if (0 == strcmp(DATALEN_KEY, key)) {
        pProgramDesc->CICSDataLength = atol(value);
    } else {
    if (0 == strcmp(SYSID_KEY, key)) {
       memset(pProgramDesc->CICSSysID, ' ', SYSID_LEN);
       memcpy(pProgramDesc->CICSSysID, value, strlen(value));
    } else {
    if (0 == strcmp(SYNCONRET_KEY, key)) {
        pProgramDesc->CICSSyncOnReturn = atol(value);
    } else {
    if (0 == strcmp(TRANSID_KEY, key)) {
        memset(pProgramDesc->CICSTransID, ' ', TRANSID_LEN);
        memcpy(pProgramDesc->CICSTransID, value, strlen(value));
    } else {
     if (0 == strcmp(CHANNEL_KEY, key)) {
        memset(pProgramDesc->CICSChannel, ' ', CHANNEL_NAME_LEN);
        memcpy(pProgramDesc->CICSChannel, value, strlen(value));
    }}}}}}}
    return OK_CODE;
}
Ejemplo n.º 14
0
int main(int argc, char *argv[])
{
	traceMessage("Server will be started ...");

	// on retrouve de façon dynamique le repertoire parent du programme.
	int i = strlen(argv[0]);

	while(argv[0][i] != '/')
		i--;

	if(i == 0)
		i = 1;

	argv[0][i] = '\0';

	// on repositionne le repertoire de travail.
	// Indispensable pour accéder aux fichiers de configuration de l'application si celle-ci est lance depuis un autre repertoire que celui qui contient l'application.
	chdir(argv[0]);

	authentificationThread();
}
Ejemplo n.º 15
0
/*====================================================================*/
int processKeyArray(char* key,
                    char* value,
                    CICSProgramDesc* pProgramDesc) {

    char itemValue[MAX_VALUE_LEN];
    char* remaining = value;
    int pos = 0;
    int maxSize = MAX_OUT_CONTAINERS * (CONTAINER_NAME_LEN + 1);

    if (value == NULL || strlen(value) == 0) {
        logError(MODULE_NAME, "Key found with no associated value.");
        return ERROR_CODE;
    }

    if (g_pTraceParms->traceMode == TRUE_CODE) {
        sprintf(g_traceMessage,
            "processKeyArray key=%s value=%s", key, value);
        traceMessage(MODULE_NAME, g_traceMessage);
    }

    if (0 == strcmp(OUTCONTAINERS_KEY, key)) {
        /* Get the first item value */
        remaining = getToken(
                       remaining, itemValue, MAX_VALUE_LEN - 1,
                       VALUE_DELIM, VALUE_DELIM);
        while(itemValue != NULL
                && strlen(itemValue) > 0 && pos < maxSize) {
            memcpy(pProgramDesc->CICSOutputContainers + pos,
                   itemValue, strlen(itemValue));
            pProgramDesc->CICSOutputContainersCount += 1;
            pos += (CONTAINER_NAME_LEN + 1);
            remaining = getToken(
                           remaining, itemValue, MAX_VALUE_LEN - 1,
                           VALUE_DELIM, VALUE_DELIM);
        }
    }

    return OK_CODE;
}
Ejemplo n.º 16
0
AccountsList* loadAccountsFromFile(const char *filename)
{
	int file_descriptor = open(filename, O_RDONLY);

	if(file_descriptor < 0)
	{
		if(errno == ENOENT)
			errorMessage("File \"%s\" doesn't exist.", filename);
		else
			errorMessage("File \"%s\" can't be opened.", filename);
		return NULL;
	}

	unsigned int nb_accounts;
	int return_value = readUIntFromFile(file_descriptor, &nb_accounts, ';');
	if(return_value < 0)
	{
		if(return_value == -2)
			errorMessage("Number of accounts not found in file.");
		else
			errorMessage("An error has occurred while reading file.");

		close(file_descriptor);
		return NULL;
	}
	goAfterCharacterInFile(file_descriptor, ';');

	AccountsList *list = createAccountsList(nb_accounts);
	traceMessage("Accounts list of length %d created", (int) nb_accounts);
	char buffer1[50], buffer2[50], *login, *password;
	unsigned int tmp;
	int x, y;

	int i;
	for(i=0; i<nb_accounts; i++)
	{
		// lecture du login.
		if(readStringFromFile(file_descriptor, buffer1, 50, ':') < 0 || (login = extractStringWithoutSpace(buffer1)) == NULL)
		{
			destroyAccountsList(list);
			close(file_descriptor);
			return NULL;
		}
		if(!isCorrectLoginOrPassword(login))
		{
			warningMessage("Login \"%s\" readed in file is syntactically false. Accounts list can't be load from file.", login);
			destroyAccountsList(list);
			close(file_descriptor);
			return NULL;
		}
		goAfterCharacterInFile(file_descriptor, ':');

		// Lecture du mot de passe.
		if(readStringFromFile(file_descriptor, buffer2, 50, ':') < 0 || (password = extractStringWithoutSpace(buffer2)) == NULL)
		{
			destroyAccountsList(list);
			close(file_descriptor);
			return NULL;
		}
		if(!isCorrectLoginOrPassword(password))
		{
			warningMessage("Password \"%s\" readed in file is syntactically false. Accounts list can't be load from file.", password);
			destroyAccountsList(list);
			close(file_descriptor);
			return NULL;
		}
		goAfterCharacterInFile(file_descriptor, ':');

		// lecture de x.
		return_value = readUIntFromFile(file_descriptor, &tmp, ':');
		if(return_value == -1)
		{
			errorMessage("An error has occurred while reading file.");
			destroyAccountsList(list);
			close(file_descriptor);
			return NULL;
		}
		else if(return_value == -2)
			x = -1;
		else
			x = (int) tmp;
		goAfterCharacterInFile(file_descriptor, ':');

		// Lecture de y si necessaire.
		if(x != -1)
		{
			return_value = readUIntFromFile(file_descriptor, &tmp, ';');
			if(return_value == -1)
			{
				errorMessage("An error has occurred while reading file.");
				destroyAccountsList(list);
				close(file_descriptor);
				return NULL;
			}
			else if(return_value == -2)
				x = y = -1;
			else
				y = (int) tmp;
		}
		else
			y = -1;

		goAfterCharacterInFile(file_descriptor, ';');

		addAccountToList(list, login, password, x, y);
	}

	close(file_descriptor);
	return list;
}
Ejemplo n.º 17
0
/*====================================================================*/
int linkCommarea(DFHEIBLK *inDfheiptr,
                TraceParms* inTraceParms,
                CICSProgramDesc* pProgramDesc,
                Message* pRequestMessage,
                Message* pResponseMessage) {
    char* inputContent;
    dfheiptr = inDfheiptr;
    g_pTraceParms = inTraceParms;
    initLog(dfheiptr, inTraceParms);

    if (g_pTraceParms->traceMode == TRUE_CODE) {
       traceMessage(MODULE_NAME, "Entered linkCommarea");
    }

    if (OK_CODE != checkCommarea(pProgramDesc, pRequestMessage)) {
        return ERROR_CODE;
    }

    /* The commarea expected by the target program might be larger
     * than the content of the incoming message part. In this case,
     * we need to rebuild the commarea. */
    if (pProgramDesc->CICSLength >
              pRequestMessage->pParts->size.as_int) {
        reallocContent(pProgramDesc, pRequestMessage->pParts);
    }
    inputContent = pRequestMessage->pParts->content;

    /* COMMENT OUT UNLESS STORAGE DEBUGGING
    sprintf(g_traceMessage, "Storage before LINK PROGRAM(%s)",
          pProgramDesc->CICSProgram);
    traceMessage(MODULE_NAME, g_traceMessage);
    traceStorage(); */
    
     /*  Now link to CICS program and check for errors                */
    if (strlen(pProgramDesc->CICSSysID) == 0) {
        if (FALSE_CODE == pProgramDesc->CICSSyncOnReturn) {
            if (strlen(pProgramDesc->CICSTransID) == 0) {
                EXEC CICS LINK
                          PROGRAM(pProgramDesc->CICSProgram)
                          COMMAREA(inputContent)
                          LENGTH(pProgramDesc->CICSLength)
                          DATALENGTH(pProgramDesc->CICSDataLength)
                          RESP(g_cicsResp) RESP2(g_cicsResp2);
            } else {
                EXEC CICS LINK
                          PROGRAM(pProgramDesc->CICSProgram)
                          COMMAREA(inputContent)
                          LENGTH(pProgramDesc->CICSLength)
                          DATALENGTH(pProgramDesc->CICSDataLength)
                          TRANSID(pProgramDesc->CICSTransID)
                          RESP(g_cicsResp) RESP2(g_cicsResp2);
            }
        } else {
            if (strlen(pProgramDesc->CICSTransID) == 0) {
                EXEC CICS LINK
                          PROGRAM(pProgramDesc->CICSProgram)
                          COMMAREA(inputContent)
                          LENGTH(pProgramDesc->CICSLength)
                          DATALENGTH(pProgramDesc->CICSDataLength)
                          SYNCONRETURN
                          RESP(g_cicsResp) RESP2(g_cicsResp2);
            } else {
                EXEC CICS LINK
                          PROGRAM(pProgramDesc->CICSProgram)
                          COMMAREA(inputContent)
                          LENGTH(pProgramDesc->CICSLength)
                          DATALENGTH(pProgramDesc->CICSDataLength)
                          TRANSID(pProgramDesc->CICSTransID)
                          SYNCONRETURN
                          RESP(g_cicsResp) RESP2(g_cicsResp2);
            }
        }
    } else {
        if (FALSE_CODE == pProgramDesc->CICSSyncOnReturn) {
            if (strlen(pProgramDesc->CICSTransID) == 0) {
                EXEC CICS LINK
                          PROGRAM(pProgramDesc->CICSProgram)
                          COMMAREA(inputContent)
                          LENGTH(pProgramDesc->CICSLength)
                          DATALENGTH(pProgramDesc->CICSDataLength)
                          SYSID(pProgramDesc->CICSSysID)
                          RESP(g_cicsResp) RESP2(g_cicsResp2);
            } else {
                EXEC CICS LINK
                          PROGRAM(pProgramDesc->CICSProgram)
                          COMMAREA(inputContent)
                          LENGTH(pProgramDesc->CICSLength)
                          DATALENGTH(pProgramDesc->CICSDataLength)
                          SYSID(pProgramDesc->CICSSysID)
                          TRANSID(pProgramDesc->CICSTransID)
                          RESP(g_cicsResp) RESP2(g_cicsResp2);
            }
        } else {
            if (strlen(pProgramDesc->CICSTransID) == 0) {
                EXEC CICS LINK
                          PROGRAM(pProgramDesc->CICSProgram)
                          COMMAREA(inputContent)
                          LENGTH(pProgramDesc->CICSLength)
                          DATALENGTH(pProgramDesc->CICSDataLength)
                          SYSID(pProgramDesc->CICSSysID)
                          SYNCONRETURN
                          RESP(g_cicsResp) RESP2(g_cicsResp2);
            } else {
                EXEC CICS LINK
                          PROGRAM(pProgramDesc->CICSProgram)
                          COMMAREA(inputContent)
                          LENGTH(pProgramDesc->CICSLength)
                          DATALENGTH(pProgramDesc->CICSDataLength)
                          SYSID(pProgramDesc->CICSSysID)
                          TRANSID(pProgramDesc->CICSTransID)
                          SYNCONRETURN
                          RESP(g_cicsResp) RESP2(g_cicsResp2);
            }
        }
    }

    if (g_cicsResp != DFHRESP(NORMAL)) {
        logCicsError(MODULE_NAME, "LINK COMMAREA",
                     g_cicsResp,g_cicsResp2);
        return ERROR_CODE;
    }

    /* COMMENT OUT UNLESS STORAGE DEBUGGING
    sprintf(g_traceMessage, "Storage after LINK PROGRAM(%s)",
          pProgramDesc->CICSProgram);
    traceMessage(MODULE_NAME, g_traceMessage);
    traceStorage(); */
    
    if (OK_CODE != formatCommareaResponse(
                   pProgramDesc, pRequestMessage, pResponseMessage)) {
        return ERROR_CODE;
    }

    if (g_pTraceParms->traceMode == TRUE_CODE) {
       traceMessage(MODULE_NAME, "Return from linkCommarea");
    }

    return OK_CODE;
}