CPICINIT.C
/* need to look for SUPPORTS_SETTING_SECURITY before using XC_SECURITY*     */ 
/***************************************************************************** 
 * 
 *  MODULE NAME: CPICINIT.C 
 * 
 *  COPYRIGHTS: 
 *             This module contains code made available by IBM 
 *             Corporation on an AS IS basis.  Any one receiving the 
 *             module is considered to be licensed under IBM copyrights 
 *             to use the IBM-provided source code in any way he or she 
 *             deems fit, including copying it, compiling it, modifying 
 *             it, and redistributing it, with or without 
 *             modifications.  No license under any IBM patents or 
 *             patent applications is to be implied from this copyright 
 *             license. 
 * 
 *             A user of the module should understand that IBM cannot 
 *             provide technical support for the module and will not be 
 *             responsible for any consequences of use of the program. 
 * 
 *             Any notices, including this one, are not to be removed 
 *             from the module without the prior written consent of 
 *             IBM. 
 * 
 *  AUTHOR:    Peter J. Schwaller 
 *             VNET:     PJS at RALVM6           Tie Line: 444-4376 
 *             Internet: pjs@ralvm6.vnet.ibm.com     (919) 254-4376 
 * 
 *  FUNCTION:  Provides procedures to be used in programs to help them set up 
 *             all of the partner program information for CPI-C.  All of the 
 *             information is stored in a CPICINIT structure.  The 
 *             information is stored in the structure using default and set 
 *             calls. 
 * 
 *             The cpicinit_setup_conversation procedure can then be used 
 *             to issue the CPI-C calls to setup a conversation_id. 
 *             All of the CPI-C calls from CMINIT to just before CMALLC 
 *             are issued.  The program should issue CMALLC on its own 
 *             so it can control error handling. 
 * 
 *             By collecting all of the partner program information within 
 *             a single object, restarting a conversation that has failed 
 *             is made easier, since the information does not have to 
 *             be collected or read from a profile again. 
 * 
 *  AVAILABILITY: 
 *             These sample programs and source are also available on 
 *             CompuServe through the APPC Information Exchange.  To get 
 *             to the APPC forum just type 'GO APPC' from any CompuServe 
 *             prompt.  The samples are available in the Sample Programs 
 *             library section.  Just search on the keyword CPICPGMS to 
 *             find all the samples in this series. 
 * 
 *             Updates for the sample programs and support for many more 
 *             CPI-C platforms will also be made available on CompuServe. 
 * 
 *  RELATED FILES: 
 *             Uses CPICINIT.H 
 * 
 *  CHANGE HISTORY: 
 *  Date       Description 
 *  08/05/92   Version 2.31 of APING, ATELL and AREXEC released to CompuServe. 
 *             This version was also distributed at the APPC/APPN Platform 
 *             Developer's Conference held in Raleigh, NC. 
 *  08/13/92   Changed all printf and fprintf calls to use a write_*() call. 
 *  08/18/92   Fixed problem with imbedded \0 added setting def_sym_dest_name 
 *             in cpicinit_default_sym_dest_name().  This fixes a problem 
 *             seen in MVS. 
 *  08/23/92   Removed cpicinit_default_destination() and associated 
 *             processing.   After review, we decided that this call was 
 *             extraneous and that cpicinit_default_sym_dest_name() was 
 *             a better mechanism for a default destination. 
 *  11/13/92   Changed most return values from TRUE/FALSE to CPICINIT_OK and 
 *             other return codes. 
 * 
 *****************************************************************************/ 
 
/***************************************************************************** 
 * 
 * OVERVIEW OF CPICINIT CALLS 
 * 
 * cpicinit_new()                     Creates a CPICINIT object. 
 *                                    This must be done before any other 
 *                                    cpicinit calls can be used. 
 * 
 * cpicinit_default_tp_name()         These calls set the initial values 
 * cpicinit_default_mode_name()       for CPICINIT parameters.  These should 
 * cpicinit_default_sym_dest_name()   all be issued right after the CPICINIT 
 *                                    object is created.  Usually, these calls 
 *                                    should set the values that should be used 
 *                                    only if the user does not specify new 
 *                                    values. 
 * 
 * cpicinit_set_tp_name()             These calls also set the values for 
 * cpicinit_set_mode_name()           CPICINIT parameters.  These calls should 
 * cpicinit_set_destination()         be used to set values from user input 
 *                                    or profile values.  These calls should be 
 *                                    used after the user has specified values, 
 *                                    through command line parameters, program 
 *                                    profiles, or interactive input. 
 * 
 *   Security calls - only available where supported by CPI-C 
 * cpicinit_set_userid                Sets the userid for the conversation. 
 * cpicinit_set_password              Sets the password for the conversation. 
 * cpicinit_query_password_needed     If a userid was set, then a password 
 *                                    is required. 
 * cpicinit_get_password              Let cpicinit prompt the user for a 
 *                                    password. 
 * cpicinit_set_security_type         Set the security type for this conv. 
 * 
 * cpicinit_setup_conversation()      Handles all CMINIT and set calls. 
 *                                    Should be used by the calling program 
 *                                    instead of CMINIT.  See description 
 *                                    of the procedure for more details. 
 * 
 * cpicinit_destroy()                 Destroys the CPICINIT object. 
 * 
 * cpicinit_pln_valid()               These are internal calls used by 
 * cpicinit_mode_valid()              cpicinit_setup_conversation. 
 * 
 *****************************************************************************/ 
 
#if defined(WIN32) || defined(WINDOWS) 
#include <windows.h> 
#endif 
 
#include "wincpic.h" 
 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
 
 
/* CPI-C error handling routines */ 
#include "cpicerrs.h" 
 
/* CPI-C initialization routines */ 
#include "cpicinit.h" 
 
/* Collection of routines with special ported version for each platform */ 
#include "cpicport.h" 
 
 
/****************************************************************************** 
 * 
 *  cpicinit_new 
 * 
 *  Creates a new CPICINIT object and returns its handle to the caller. 
 *  This object handle must be used on all subsequent cpicinit calls. 
 *  All internal fields are initialized appropriately. 
 * 
 *  If memory cannot be allocated for the CPICINIT object, NULL will be 
 *  returned as the result of the call.  Otherwise, the return value will 
 *  be a pointer to the CPICINIT object. 
 * 
 *****************************************************************************/ 
CPICINIT * 
cpicinit_new(void) 
{ 
    CPICINIT * cpicinit; 
 
    cpicinit = (CPICINIT *) malloc(sizeof(*cpicinit)); 
    if (cpicinit == NULL) { 
        return NULL; 
    } 
 
    /* Initialize the entire structure to 0's */ 
    memset(cpicinit, 
           0, 
           sizeof(*cpicinit)); 
 
    /* Set the default symbolic destination name to BLANKs. */ 
    /* This is the "default-default" if nothing else is set. */ 
    memset(cpicinit -> def_sym_dest_name, 
           ' ', 
           sizeof(cpicinit->def_sym_dest_name)); 
    cpicinit->def_sym_dest_name[sizeof(cpicinit->def_sym_dest_name)-1] = '\0'; 
 
    /* Indicate that the values have not yet been SET */ 
    cpicinit -> set_mode_name = NOT_SET; 
    cpicinit -> set_destination = NOT_SET; 
    cpicinit -> set_tp_name = NOT_SET; 
    cpicinit -> set_userid = NOT_SET; 
    cpicinit -> set_password = NOT_SET; 
    cpicinit -> security_type = XC_SECURITY_SAME; 
 
    /* 
     * This flag is usedby other cpicinit calls to decide whether or not 
     * to show errors encountered during processing. 
     * 
     * If this value is turned off, the cpicinit routines will not produce 
     * any output, even in the event of an error. 
     */ 
    cpicinit -> show_error = SET; 
 
 
    /* return a pointer to the structure */ 
    return cpicinit; 
} 
 
/****************************************************************************** 
 * 
 *  cpicinit_default_sym_dest_name 
 * 
 *  Sets a symbolic destination name to be used if no call is made to 
 *  cpicinit_set_destination(). 
 * 
 *  Returns: 
 *    CPICINIT_OK,     if there was no error. 
 *    CPICINIT_ERROR,  if there was an error. 
 * 
 *****************************************************************************/ 
int 
cpicinit_default_sym_dest_name( CPICINIT * cpicinit, 
                                char *     def_sym_dest_name) 
/* 
 * Set the default symbolic destination name to be used if no destination 
 * is ever set. 
 */ 
{ 
    int length; 
    int rc; 
 
 
    /* Set the default symbolic destination name to BLANKs. */ 
    memset(cpicinit -> def_sym_dest_name, 
           ' ', 
           sizeof(cpicinit->def_sym_dest_name)); 
    cpicinit->def_sym_dest_name[sizeof(cpicinit->def_sym_dest_name)-1] = '\0'; 
 
    length = strlen(def_sym_dest_name); 
 
    if (length < sizeof(cpicinit->def_sym_dest_name)) { 
        rc = CPICINIT_ERROR; 
        memcpy(cpicinit->def_sym_dest_name, 
               def_sym_dest_name, 
               length); 
    } else { 
        rc = CPICINIT_OK; 
    } 
 
    return rc; 
} 
 
/****************************************************************************** 
 * 
 *  cpicinit_default_tp_name 
 * 
 *  Sets a symbolic destination name to be used if no call is made to 
 *  cpicinit_set_destination(). 
 * 
 *  Returns: 
 *    CPICINIT_OK,     if there was no error. 
 *    CPICINIT_ERROR,  if there was an error. 
 * 
 *****************************************************************************/ 
int 
cpicinit_default_tp_name(CPICINIT * cpicinit, 
                         char *     tp_name) 
/* initialize the tp_name */ 
{ 
    int length; 
    int rc; 
 
    length = strlen(tp_name); 
 
    if (length < sizeof(cpicinit->tp_name)) { 
        rc = CPICINIT_ERROR; 
        memcpy(cpicinit->tp_name, 
               tp_name, 
               length); 
        cpicinit->tp_name[length] = '\0'; 
    } else { 
        rc = CPICINIT_OK; 
        if (cpicinit -> show_error) { 
             write_error( 
                     "The TP name you specified is too long:\n%s\n", 
                     tp_name); 
             write_error( 
                    "The maximum length of a TP name is %u characters.\n", 
                    sizeof(cpicinit->tp_name)-1); 
             write_error( 
                     "TP name of %s will be used.\n", cpicinit->tp_name); 
        } 
    } 
 
    return rc; 
} 
 
/****************************************************************************** 
 * 
 *  cpicinit_default_mode_name 
 * 
 *  Sets the default mode name to be used if there is no call made to 
 *  cpicinit_set_mode_name(). 
 * 
 *  Returns: 
 *    CPICINIT_OK,     if there was no error. 
 *    CPICINIT_ERROR,  if there was an error. 
 * 
 *****************************************************************************/ 
int 
cpicinit_default_mode_name(CPICINIT * cpicinit, 
                           char *     mode_name) 
/* initialize the mode name */ 
{ 
    int length; 
    int rc; 
 
    length = strlen(mode_name); 
 
    if (length < sizeof(cpicinit->mode_name)) { 
        rc = CPICINIT_ERROR; 
        memcpy(cpicinit->mode_name, 
               mode_name, 
               length); 
        cpicinit->mode_name[length] = '\0'; 
        strupr(cpicinit->mode_name); 
    } else { 
        rc = CPICINIT_OK; 
        if (cpicinit -> show_error) { 
            write_error( 
                    "The mode name you specified is too long:\n%s\n", 
                    mode_name); 
            write_error( 
                   "The maximum length of a mode name is %u characters.\n", 
                   sizeof(cpicinit->mode_name)-1); 
            write_error( 
                   "Mode name of %s will be used.\n", cpicinit->mode_name); 
        } 
    } 
 
    return rc; 
} 
 
 
/* 
 * The major difference between the default calls above and the set calls 
 * below is the setting of a flag in the set calls indicating that the user 
 * has specified this value.  This flag is used later as an indication that 
 * any value set by the symbolic destination name entries should be 
 * overridden. 
 */ 
 
 
/****************************************************************************** 
 * 
 *  cpicinit_set_tp_name 
 * 
 *  Returns: 
 *    CPICINIT_OK,     if there was no error. 
 *    CPICINIT_ERROR,  if there was an error. 
 * 
 *****************************************************************************/ 
int 
cpicinit_set_tp_name(CPICINIT * cpicinit, 
                     char *     tp_name) 
{ 
    cpicinit->set_tp_name = SET; 
    return cpicinit_default_tp_name(cpicinit, tp_name); 
} 
 
/****************************************************************************** 
 * 
 *  cpicinit_set_mode_name 
 * 
 *  Returns: 
 *    CPICINIT_OK,     if there was no error. 
 *    CPICINIT_ERROR,  if there was an error. 
 * 
 *****************************************************************************/ 
int 
cpicinit_set_mode_name(CPICINIT * cpicinit, 
                       char *     mode_name) 
{ 
    cpicinit->set_mode_name = SET; 
    return cpicinit_default_mode_name(cpicinit, mode_name); 
} 
 
/****************************************************************************** 
 * 
 *  cpicinit_set_destination 
 * 
 *  Returns: 
 *    CPICINIT_OK,     if there was no error. 
 *    CPICINIT_ERROR,  if there was an error. 
 * 
 *****************************************************************************/ 
int 
cpicinit_set_destination(CPICINIT * cpicinit, 
                         char *     destination) 
{ 
    int length; 
    int rc; 
 
    cpicinit->set_destination = SET; 
 
    length = strlen(destination); 
 
    if (length < sizeof(cpicinit->destination)) { 
        rc = CPICINIT_ERROR; 
        memcpy(cpicinit->destination, 
               destination, 
               length); 
        cpicinit->destination[length] = '\0'; 
    } else { 
        rc = CPICINIT_OK; 
        if (cpicinit -> show_error) { 
            write_error( 
                    "The destination you specified is too long:\n%s\n", 
                    destination); 
            write_error( 
            "The maximum length of a destination is %u characters.\n", 
                sizeof(cpicinit->destination)-1); 
            write_error( 
                    "Destination %s will be used.\n", cpicinit->destination); 
        } 
    } 
 
    return rc; 
} 
 
/****************************************************************************** 
 * 
 *  cpicinit_set_userid 
 * 
 *  Sets the userid to be used for security on the conversation.  Issuing 
 *  this call implies that the conversation will use security=PROGRAM; 
 *  a password will also be required in order to get a conversation. 
 *  The password should be set using either the cpicinit_set_password() call 
 *  or the cpicinit_get_password() call. 
 * 
 *  Returns: 
 *    CPICINIT_OK,     if there was no error. 
 *    CPICINIT_ERROR,  if there was an error. 
 * 
 *****************************************************************************/ 
int 
cpicinit_set_userid(CPICINIT * cpicinit, 
                    char *     userid) 
/* initialize the userid */ 
{ 
    int length; 
    int rc; 
 
    length = strlen(userid); 
 
    if (length < sizeof(cpicinit->userid)) { 
        rc = CPICINIT_ERROR; 
        memcpy(cpicinit->userid, 
               userid, 
               length); 
        cpicinit->userid[length] = '\0'; 
        cpicinit->set_userid = SET; 
        cpicinit->security_type = XC_SECURITY_PROGRAM; 
    } else { 
        rc = CPICINIT_OK; 
        if (cpicinit -> show_error) { 
            write_error( 
                    "The userid you specified is too long:\n%s\n", 
                    userid); 
            write_error( 
                   "The maximum length of a userid is %u characters.\n", 
                   sizeof(cpicinit->userid)-1); 
        } 
    } 
 
    return rc; 
 
} 
/****************************************************************************** 
 * 
 *  cpicinit_query_password_needed 
 * 
 *  Can be used by the program to inquire whether a password will be required 
 *  to establish a conversation.  This can be used by a program instead of 
 *  keeping track itself of whether a userid has been specified.  If a password 
 *  is required, the password should be set using either the 
 *  cpicinit_set_password() call or the cpicinit_get_password() call. 
 * 
 *  Returns: 
 *    TRUE   if password is required 
 *    FALSE  if no password should be set 
 * 
 *****************************************************************************/ 
int 
cpicinit_query_password_needed(CPICINIT * cpicinit) 
{ 
    if (cpicinit->set_userid == SET && cpicinit->set_password == NOT_SET) { 
        return TRUE; 
    } else { 
        return FALSE; 
    } 
} 
 
 
/****************************************************************************** 
 * 
 *  cpicinit_set_password 
 * 
 *  Sets the password to be used with security=PROGRAM.  This call should be 
 *  used in conjunction with the cpicinit_set_userid() call. 
 * 
 *  Returns: 
 *    CPICINIT_OK,     if there was no error. 
 *    CPICINIT_ERROR,  if there was an error. 
 * 
 *****************************************************************************/ 
int 
cpicinit_set_password(CPICINIT * cpicinit, 
                    char *     password) 
/* initialize the password */ 
{ 
    int length; 
    int rc; 
 
    length = strlen(password); 
 
    if (length < sizeof(cpicinit->password)) { 
        rc = CPICINIT_ERROR; 
        memcpy(cpicinit->password, 
               password, 
               length); 
        cpicinit->password[length] = '\0'; 
        cpicinit->set_password = SET; 
        cpicinit->security_type = XC_SECURITY_PROGRAM; 
    } else { 
        rc = CPICINIT_OK; 
        if (cpicinit -> show_error) { 
            write_error( 
                    "The password you specified is too long:\n%s\n", 
                    password); 
            write_error( 
                   "The maximum length of a password is %u characters.\n", 
                   sizeof(cpicinit->password)-1); 
        } 
    } 
 
    return rc; 
} 
 
 
/****************************************************************************** 
 * 
 *  cpicinit_get_password 
 * 
 *****************************************************************************/ 
void 
cpicinit_get_password(CPICINIT * cpicinit) 
{ 
    write_output("\nPassword: ");           /* display the prompt            */ 
 
    if (!get_password(cpicinit->password, sizeof(cpicinit->password)-1)) { 
        cpicinit->set_password = SET; 
        cpicinit->security_type = XC_SECURITY_PROGRAM; 
    } 
    return; 
} 
 
/****************************************************************************** 
 * 
 *  cpicinit_set_security_type 
 * 
 *****************************************************************************/ 
void 
cpicinit_set_security_type(CPICINIT * cpicinit, 
                           unsigned long security_type) 
{ 
    cpicinit->security_type = security_type; 
} 
 
 
/****************************************************************************** 
 * 
 *  cpicinit_setup_conversation 
 * 
 *  The goal of this procedure is to initialize a CPI-C conversation ID 
 *  and make sure that partner destination information is all specified. 
 *  This destination information includes partner LU name, mode name, 
 *  and TP name. 
 * 
 *  To be as flexible as possible, the destination parameter can serve 
 *  a dual role.  If specified, the destination is first used as the 
 *  symbolic destination name.  If this does not produce a valid partner 
 *  LU name, another symbolic destination name will be used and the 
 *  destination parameter will be used instead as a partner LU name. 
 * 
 *  AN OVERVIEW OF THE PROCEDURE 
 * 
 *  If the destination was SET 
 *      use destination as a symbolic destination name 
 *      If CMINIT failed or there was no partner LU name extracted 
 *          use the default symbolic destination name or all blanks 
 *          use the destination as a partner LU name 
 * 
 *****************************************************************************/ 
int 
cpicinit_setup_conversation(CPICINIT *      cpicinit, 
                            unsigned char * cm_conv_id, 
                            CPICERR *       cpicerr) 
{ 
    CM_INT32 cm_rc = CM_OK; 
    CM_INT32 length; 
    int      dest_len; 
    char sym_dest_name[9]; 
 
    /* check if a destination was set by the cpicinit_set_destination() call */ 
    if (cpicinit->set_destination == SET) { 
 
        /* check if the destination could be a symbolic destination name     */ 
        if (((dest_len = strlen(cpicinit->destination)) < 
                                                         MAX_SYM_DEST_NAME)) { 
            /* 
             * Try to use the specified destination as a symbolic 
             * destination name.  A symbolic destination name is blank 
             * padded and must contain all uppercase characters. 
             */ 
 
            memset(sym_dest_name,           /* Initialize the sym dest name  */ 
                   ' ',                     /* to all blanks.                */ 
                   sizeof(sym_dest_name)); 
 
            memcpy(sym_dest_name,           /* Copy the destination into the */ 
                   cpicinit->destination,   /* sym dest name.                */ 
                   dest_len); 
                                            /* place the null terminator     */ 
            sym_dest_name[MAX_SYM_DEST_NAME - 1] = '\0'; 
 
            strupr(sym_dest_name);          /* sym dest must be uppercase    */ 
 
            /* 
             * Since we are using the destination as a sym_dest, make sure 
             * we don't also use it as a partner LU name. 
             */ 
            cpicinit->set_destination = NOT_SET; 
 
            cminit(cm_conv_id, 
                   (unsigned char *)sym_dest_name, 
                   &cm_rc); 
 
        } else { 
            /* 
             * The destination was too long to be a symbolic destination name. 
             */ 
        } 
 
 
 
        if (cm_rc != CM_OK || !cpicinit_pln_valid(cm_conv_id)) { 
 
            /* 
             * Since the destination was not a sym_dest, we can use it 
             * later as a partner LU name. 
             */ 
            cpicinit->set_destination = SET; 
 
            /* 
             * Try to use the default symbolic destination name.  If 
             * configured, this symbolic destination can be used to 
             * initialize the partner LU name and mode name entries, 
             * or left blank. 
             */ 
            cminit(cm_conv_id, 
                   (unsigned char *)cpicinit->def_sym_dest_name, 
                   &cm_rc); 
 
            if (cm_rc != CM_OK) { 
                /* 
                 * Nothing else worked, so let's try the blank symbolic 
                 * destination name.  All CPI-C values will be initialized 
                 * to non usable values. 
                 */ 
                cminit(cm_conv_id, 
                       (unsigned char *)BLANK_SYM_DEST_NAME, 
                       &cm_rc); 
                if (cm_rc != CM_OK) { 
                    return cpicerr_handle_rc(cpicerr, MSG_CMINIT, cm_rc); 
                } 
 
                /* 
                 * Since the blank symbolic destination name was used, 
                 * we must set the partner LU name and mode even if we 
                 * use the defaults. 
                 */ 
                cpicinit->set_destination = cpicinit->set_mode_name = SET; 
 
            } 
 
        } 
 
    } else { 
        /* 
         * Although no destination was specified, we can try to continue 
         * by using the default symbolic destination name.  If this entry 
         * is configured with a valid partner LU, we may be able to 
         * establish a connection with a partner. 
         */ 
        cminit(cm_conv_id, 
               (unsigned char * )cpicinit->def_sym_dest_name, 
               &cm_rc); 
        if (cm_rc != CM_OK) { 
            /* 
             * Fill in conversation information for CPI-C error reporting. 
             */ 
            cpicerr_set_conv_id(cpicerr, cm_conv_id); 
            return cpicerr_handle_rc(cpicerr, MSG_CMINIT, cm_rc); 
        } 
    } 
 
    /* 
     * Fill in conversation information for CPI-C error reporting. 
     */ 
    cpicerr_set_conv_id(cpicerr, cm_conv_id); 
 
    if (cpicinit->set_destination == SET) { 
        CM_INT32 dest_length; 
        dest_length = strlen(cpicinit->destination); 
 
#if defined(PLN_COULD_REQUIRE_LOWERCASE) 
        /* 
         * strupr should only be performed if the partner LU name is 
         * a fully qualified name. 
         */ 
#ifdef FAPI 
        if ((strchr(cpicinit->destination,'.') != NULL) || 
            (get_machine_mode() == 0)) { 
            strupr(cpicinit->destination); 
        } 
#else 
        if (strchr(cpicinit->destination,'.') != NULL) { 
            strupr(cpicinit->destination); 
        } 
#endif 
#else 
        strupr(cpicinit->destination); 
#endif 
 
        cmspln(cm_conv_id,                  /* Set partner LU name           */ 
               (unsigned char *)cpicinit->destination, 
               &dest_length, 
               &cm_rc); 
        if (cm_rc != CM_OK) 
            return cpicerr_handle_rc(cpicerr, MSG_CMSPLN, cm_rc); 
    } 
 
    /* 
     * Since there is no way to query the TP name, we will always set it. 
     * The default TP name can be overridden on the cpicinit_set_tp_name 
     * call. 
     */ 
 
    length = strlen(cpicinit->tp_name); 
    cmstpn(cm_conv_id,                      /* Set TP name                   */ 
           (unsigned char *)cpicinit->tp_name, 
           &length, 
           &cm_rc); 
    if (cm_rc != CM_OK) 
        return cpicerr_handle_rc(cpicerr, MSG_CMSTPN, cm_rc); 
 
    /* 
     * If there was a cpicinit_set_mode_name call made previously or 
     * present mode name is not initialized, we need to set the mode 
     * name. 
     */ 
    if ((cpicinit->set_mode_name == SET) || 
                                         !cpicinit_mode_valid(cm_conv_id)) { 
        length = strlen(cpicinit->mode_name); 
        cmsmn(cm_conv_id,                   /* Set mode name                 */ 
              (unsigned char *)cpicinit->mode_name, 
              &length, 
              &cm_rc); 
        if (cm_rc != CM_OK) 
            return cpicerr_handle_rc(cpicerr, MSG_CMSMN, cm_rc); 
    } 
 
#if defined(SUPPORTS_SETTING_SECURITY) 
    /* 
     * If there was a cpicinit_set_userid AND cpicinit_set_password call made 
     * previously, we need to set the security parameters.  The security 
     * functions are not available on all CPI-C platforms. 
     */ 
 
    if (cpicinit->security_type == XC_SECURITY_NONE) { 
        CM_INT32 security_type; 
        security_type = XC_SECURITY_NONE; 
        xcscst(cm_conv_id,                  /* Set Security Type             */ 
               &security_type, 
               &cm_rc); 
        if (cm_rc != CM_OK) 
            return cpicerr_handle_rc(cpicerr, MSG_XCSCST, cm_rc); 
    } else { 
        if ((cpicinit->set_userid == SET) && (cpicinit->set_password == SET)) { 
            CM_INT32 security_type; 
            security_type = XC_SECURITY_PROGRAM; 
            xcscst(cm_conv_id,              /* Set Security Type             */ 
                   &security_type, 
                   &cm_rc); 
            if (cm_rc != CM_OK) 
                return cpicerr_handle_rc(cpicerr, MSG_XCSCST, cm_rc); 
 
            length = strlen(cpicinit->userid); 
            xcscsu(cm_conv_id,              /* Set Security Userid           */ 
                   (unsigned char *)cpicinit->userid, 
                   &length, 
                   &cm_rc); 
            if (cm_rc != CM_OK) 
                return cpicerr_handle_rc(cpicerr, MSG_XCSCSU, cm_rc); 
 
            length = strlen(cpicinit->password); 
            xcscsp(cm_conv_id,              /* Set Security Password         */ 
                   (unsigned char *)cpicinit->password, 
                   &length, 
                   &cm_rc); 
            if (cm_rc != CM_OK) 
                return cpicerr_handle_rc(cpicerr, MSG_XCSCSP, cm_rc); 
 
        } 
    } 
 
#endif 
 
    return FALSE; 
} 
 
/****************************************************************************** 
 * 
 *  cpicinit_destroy 
 * 
 *  This function is the inverse of the cpicinit_new() call.  All memory 
 *  allocated by cpicinit_new() is freed. 
 * 
 *  This function has no return code. 
 * 
 *****************************************************************************/ 
void 
cpicinit_destroy(CPICINIT * cpicinit) 
{ 
    free(cpicinit); 
    return; 
} 
 
/****************************************************************************** 
 * 
 *  cpicinit_pln_valid 
 * 
 *  Internal function, used by cpic_setup_conversation(). 
 * 
 *  This function is used after a cminit() call to ensure that there was 
 *  a partner LU name configured with the symbolic destination used on 
 *  cminit().  If there was no partner LU name configured with the symbolic 
 *  destination name, a partner LU name will have to be set with the cmspln() 
 *  call. 
 * 
 *  Returns: 
 *    TRUE  if a partner LU name was configured 
 *    FALSE is there was no partner LU name configured 
 * 
 *****************************************************************************/ 
int 
cpicinit_pln_valid(unsigned char * cm_conv_id) 
{ 
    unsigned char  destination[MAX_DESTINATION]; /* variable to store the    */ 
                                            /* extracted partner LU name     */ 
    CM_INT32       length = 0;              /* length of partner LU name     */ 
    CM_RETURN_CODE cm_rc;                   /* CPI-C return code             */ 
    int            rc;                      /* procedure return code         */ 
 
    cmepln(cm_conv_id,                      /* extract partner LU name       */ 
           destination, 
           &length,                         /* length of partner LU name     */ 
           &cm_rc ); 
 
    if (cm_rc != CM_OK || (length == 1 && destination[0] == ' ')) { 
        rc = FALSE; 
    } else { 
        rc = TRUE; 
    } 
    return rc; 
} 
 
/****************************************************************************** 
 * 
 *  cpicinit_mode_valid 
 * 
 *  Internal function, used by cpic_setup_conversation(). 
 * 
 *  This function is used after a cminit() call to ensure that there was 
 *  a mode name configured with the symbolic destination used on  cminit(). 
 *  If there was no mode name configured with the symbolic destination name, 
 *  a partner LU name will have to be set with the cmsmn() call. 
 * 
 *  Returns: 
 *    TRUE  if a mode name was configured 
 *    FALSE is there was no mode name configured 
 * 
 *****************************************************************************/ 
cpicinit_mode_valid(unsigned char * cm_conv_id) 
{ 
    unsigned char  mode[MAX_MODE_NAME];     /* variable to store the         */ 
                                            /* extracted mode name           */ 
    CM_INT32       length = 0;              /* length of mode name           */ 
    CM_RETURN_CODE cm_rc;                   /* CPI-C return code             */ 
    int            rc;                      /* procedure return code         */ 
 
    cmemn(cm_conv_id,                       /* extract mode name             */ 
          mode, 
          &length, 
          &cm_rc ); 
 
    if (cm_rc != CM_OK || length == 0) { 
        rc = FALSE; 
    } else { 
        rc = TRUE; 
    } 
    return rc; 
 
}