home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / netds / sna / shared / cpicinit.c < prev    next >
Text File  |  1997-04-09  |  33KB  |  920 lines

  1. /* need to look for SUPPORTS_SETTING_SECURITY before using XC_SECURITY*     */
  2. /*****************************************************************************
  3.  *
  4.  *  MODULE NAME: CPICINIT.C
  5.  *
  6.  *  COPYRIGHTS:
  7.  *             This module contains code made available by IBM
  8.  *             Corporation on an AS IS basis.  Any one receiving the
  9.  *             module is considered to be licensed under IBM copyrights
  10.  *             to use the IBM-provided source code in any way he or she
  11.  *             deems fit, including copying it, compiling it, modifying
  12.  *             it, and redistributing it, with or without
  13.  *             modifications.  No license under any IBM patents or
  14.  *             patent applications is to be implied from this copyright
  15.  *             license.
  16.  *
  17.  *             A user of the module should understand that IBM cannot
  18.  *             provide technical support for the module and will not be
  19.  *             responsible for any consequences of use of the program.
  20.  *
  21.  *             Any notices, including this one, are not to be removed
  22.  *             from the module without the prior written consent of
  23.  *             IBM.
  24.  *
  25.  *  AUTHOR:    Peter J. Schwaller
  26.  *             VNET:     PJS at RALVM6           Tie Line: 444-4376
  27.  *             Internet: pjs@ralvm6.vnet.ibm.com     (919) 254-4376
  28.  *
  29.  *  FUNCTION:  Provides procedures to be used in programs to help them set up
  30.  *             all of the partner program information for CPI-C.  All of the
  31.  *             information is stored in a CPICINIT structure.  The
  32.  *             information is stored in the structure using default and set
  33.  *             calls.
  34.  *
  35.  *             The cpicinit_setup_conversation procedure can then be used
  36.  *             to issue the CPI-C calls to setup a conversation_id.
  37.  *             All of the CPI-C calls from CMINIT to just before CMALLC
  38.  *             are issued.  The program should issue CMALLC on its own
  39.  *             so it can control error handling.
  40.  *
  41.  *             By collecting all of the partner program information within
  42.  *             a single object, restarting a conversation that has failed
  43.  *             is made easier, since the information does not have to
  44.  *             be collected or read from a profile again.
  45.  *
  46.  *  AVAILABILITY:
  47.  *             These sample programs and source are also available on
  48.  *             CompuServe through the APPC Information Exchange.  To get
  49.  *             to the APPC forum just type 'GO APPC' from any CompuServe
  50.  *             prompt.  The samples are available in the Sample Programs
  51.  *             library section.  Just search on the keyword CPICPGMS to
  52.  *             find all the samples in this series.
  53.  *
  54.  *             Updates for the sample programs and support for many more
  55.  *             CPI-C platforms will also be made available on CompuServe.
  56.  *
  57.  *  RELATED FILES:
  58.  *             Uses CPICINIT.H
  59.  *
  60.  *  CHANGE HISTORY:
  61.  *  Date       Description
  62.  *  08/05/92   Version 2.31 of APING, ATELL and AREXEC released to CompuServe.
  63.  *             This version was also distributed at the APPC/APPN Platform
  64.  *             Developer's Conference held in Raleigh, NC.
  65.  *  08/13/92   Changed all printf and fprintf calls to use a write_*() call.
  66.  *  08/18/92   Fixed problem with imbedded \0 added setting def_sym_dest_name
  67.  *             in cpicinit_default_sym_dest_name().  This fixes a problem
  68.  *             seen in MVS.
  69.  *  08/23/92   Removed cpicinit_default_destination() and associated
  70.  *             processing.   After review, we decided that this call was
  71.  *             extraneous and that cpicinit_default_sym_dest_name() was
  72.  *             a better mechanism for a default destination.
  73.  *  11/13/92   Changed most return values from TRUE/FALSE to CPICINIT_OK and
  74.  *             other return codes.
  75.  *
  76.  *****************************************************************************/
  77.  
  78. /*****************************************************************************
  79.  *
  80.  * OVERVIEW OF CPICINIT CALLS
  81.  *
  82.  * cpicinit_new()                     Creates a CPICINIT object.
  83.  *                                    This must be done before any other
  84.  *                                    cpicinit calls can be used.
  85.  *
  86.  * cpicinit_default_tp_name()         These calls set the initial values
  87.  * cpicinit_default_mode_name()       for CPICINIT parameters.  These should
  88.  * cpicinit_default_sym_dest_name()   all be issued right after the CPICINIT
  89.  *                                    object is created.  Usually, these calls
  90.  *                                    should set the values that should be used
  91.  *                                    only if the user does not specify new
  92.  *                                    values.
  93.  *
  94.  * cpicinit_set_tp_name()             These calls also set the values for
  95.  * cpicinit_set_mode_name()           CPICINIT parameters.  These calls should
  96.  * cpicinit_set_destination()         be used to set values from user input
  97.  *                                    or profile values.  These calls should be
  98.  *                                    used after the user has specified values,
  99.  *                                    through command line parameters, program
  100.  *                                    profiles, or interactive input.
  101.  *
  102.  *   Security calls - only available where supported by CPI-C
  103.  * cpicinit_set_userid                Sets the userid for the conversation.
  104.  * cpicinit_set_password              Sets the password for the conversation.
  105.  * cpicinit_query_password_needed     If a userid was set, then a password
  106.  *                                    is required.
  107.  * cpicinit_get_password              Let cpicinit prompt the user for a
  108.  *                                    password.
  109.  * cpicinit_set_security_type         Set the security type for this conv.
  110.  *
  111.  * cpicinit_setup_conversation()      Handles all CMINIT and set calls.
  112.  *                                    Should be used by the calling program
  113.  *                                    instead of CMINIT.  See description
  114.  *                                    of the procedure for more details.
  115.  *
  116.  * cpicinit_destroy()                 Destroys the CPICINIT object.
  117.  *
  118.  * cpicinit_pln_valid()               These are internal calls used by
  119.  * cpicinit_mode_valid()              cpicinit_setup_conversation.
  120.  *
  121.  *****************************************************************************/
  122.  
  123. #if defined(WIN32) || defined(WINDOWS)
  124. #include <windows.h>
  125. #endif
  126.  
  127. #include "wincpic.h"
  128.  
  129. #include <stdio.h>
  130. #include <stdlib.h>
  131. #include <string.h>
  132.  
  133.  
  134. /* CPI-C error handling routines */
  135. #include "cpicerrs.h"
  136.  
  137. /* CPI-C initialization routines */
  138. #include "cpicinit.h"
  139.  
  140. /* Collection of routines with special ported version for each platform */
  141. #include "cpicport.h"
  142.  
  143.  
  144. /******************************************************************************
  145.  *
  146.  *  cpicinit_new
  147.  *
  148.  *  Creates a new CPICINIT object and returns its handle to the caller.
  149.  *  This object handle must be used on all subsequent cpicinit calls.
  150.  *  All internal fields are initialized appropriately.
  151.  *
  152.  *  If memory cannot be allocated for the CPICINIT object, NULL will be
  153.  *  returned as the result of the call.  Otherwise, the return value will
  154.  *  be a pointer to the CPICINIT object.
  155.  *
  156.  *****************************************************************************/
  157. CPICINIT *
  158. cpicinit_new(void)
  159. {
  160.     CPICINIT * cpicinit;
  161.  
  162.     cpicinit = (CPICINIT *) malloc(sizeof(*cpicinit));
  163.     if (cpicinit == NULL) {
  164.         return NULL;
  165.     }
  166.  
  167.     /* Initialize the entire structure to 0's */
  168.     memset(cpicinit,
  169.            0,
  170.            sizeof(*cpicinit));
  171.  
  172.     /* Set the default symbolic destination name to BLANKs. */
  173.     /* This is the "default-default" if nothing else is set. */
  174.     memset(cpicinit -> def_sym_dest_name,
  175.            ' ',
  176.            sizeof(cpicinit->def_sym_dest_name));
  177.     cpicinit->def_sym_dest_name[sizeof(cpicinit->def_sym_dest_name)-1] = '\0';
  178.  
  179.     /* Indicate that the values have not yet been SET */
  180.     cpicinit -> set_mode_name = NOT_SET;
  181.     cpicinit -> set_destination = NOT_SET;
  182.     cpicinit -> set_tp_name = NOT_SET;
  183.     cpicinit -> set_userid = NOT_SET;
  184.     cpicinit -> set_password = NOT_SET;
  185.     cpicinit -> security_type = XC_SECURITY_SAME;
  186.  
  187.     /*
  188.      * This flag is usedby other cpicinit calls to decide whether or not
  189.      * to show errors encountered during processing.
  190.      *
  191.      * If this value is turned off, the cpicinit routines will not produce
  192.      * any output, even in the event of an error.
  193.      */
  194.     cpicinit -> show_error = SET;
  195.  
  196.  
  197.     /* return a pointer to the structure */
  198.     return cpicinit;
  199. }
  200.  
  201. /******************************************************************************
  202.  *
  203.  *  cpicinit_default_sym_dest_name
  204.  *
  205.  *  Sets a symbolic destination name to be used if no call is made to
  206.  *  cpicinit_set_destination().
  207.  *
  208.  *  Returns:
  209.  *    CPICINIT_OK,     if there was no error.
  210.  *    CPICINIT_ERROR,  if there was an error.
  211.  *
  212.  *****************************************************************************/
  213. int
  214. cpicinit_default_sym_dest_name( CPICINIT * cpicinit,
  215.                                 char *     def_sym_dest_name)
  216. /*
  217.  * Set the default symbolic destination name to be used if no destination
  218.  * is ever set.
  219.  */
  220. {
  221.     int length;
  222.     int rc;
  223.  
  224.  
  225.     /* Set the default symbolic destination name to BLANKs. */
  226.     memset(cpicinit -> def_sym_dest_name,
  227.            ' ',
  228.            sizeof(cpicinit->def_sym_dest_name));
  229.     cpicinit->def_sym_dest_name[sizeof(cpicinit->def_sym_dest_name)-1] = '\0';
  230.  
  231.     length = strlen(def_sym_dest_name);
  232.  
  233.     if (length < sizeof(cpicinit->def_sym_dest_name)) {
  234.         rc = CPICINIT_ERROR;
  235.         memcpy(cpicinit->def_sym_dest_name,
  236.                def_sym_dest_name,
  237.                length);
  238.     } else {
  239.         rc = CPICINIT_OK;
  240.     }
  241.  
  242.     return rc;
  243. }
  244.  
  245. /******************************************************************************
  246.  *
  247.  *  cpicinit_default_tp_name
  248.  *
  249.  *  Sets a symbolic destination name to be used if no call is made to
  250.  *  cpicinit_set_destination().
  251.  *
  252.  *  Returns:
  253.  *    CPICINIT_OK,     if there was no error.
  254.  *    CPICINIT_ERROR,  if there was an error.
  255.  *
  256.  *****************************************************************************/
  257. int
  258. cpicinit_default_tp_name(CPICINIT * cpicinit,
  259.                          char *     tp_name)
  260. /* initialize the tp_name */
  261. {
  262.     int length;
  263.     int rc;
  264.  
  265.     length = strlen(tp_name);
  266.  
  267.     if (length < sizeof(cpicinit->tp_name)) {
  268.         rc = CPICINIT_ERROR;
  269.         memcpy(cpicinit->tp_name,
  270.                tp_name,
  271.                length);
  272.         cpicinit->tp_name[length] = '\0';
  273.     } else {
  274.         rc = CPICINIT_OK;
  275.         if (cpicinit -> show_error) {
  276.              write_error(
  277.                      "The TP name you specified is too long:\n%s\n",
  278.                      tp_name);
  279.              write_error(
  280.                     "The maximum length of a TP name is %u characters.\n",
  281.                     sizeof(cpicinit->tp_name)-1);
  282.              write_error(
  283.                      "TP name of %s will be used.\n", cpicinit->tp_name);
  284.         }
  285.     }
  286.  
  287.     return rc;
  288. }
  289.  
  290. /******************************************************************************
  291.  *
  292.  *  cpicinit_default_mode_name
  293.  *
  294.  *  Sets the default mode name to be used if there is no call made to
  295.  *  cpicinit_set_mode_name().
  296.  *
  297.  *  Returns:
  298.  *    CPICINIT_OK,     if there was no error.
  299.  *    CPICINIT_ERROR,  if there was an error.
  300.  *
  301.  *****************************************************************************/
  302. int
  303. cpicinit_default_mode_name(CPICINIT * cpicinit,
  304.                            char *     mode_name)
  305. /* initialize the mode name */
  306. {
  307.     int length;
  308.     int rc;
  309.  
  310.     length = strlen(mode_name);
  311.  
  312.     if (length < sizeof(cpicinit->mode_name)) {
  313.         rc = CPICINIT_ERROR;
  314.         memcpy(cpicinit->mode_name,
  315.                mode_name,
  316.                length);
  317.         cpicinit->mode_name[length] = '\0';
  318.         strupr(cpicinit->mode_name);
  319.     } else {
  320.         rc = CPICINIT_OK;
  321.         if (cpicinit -> show_error) {
  322.             write_error(
  323.                     "The mode name you specified is too long:\n%s\n",
  324.                     mode_name);
  325.             write_error(
  326.                    "The maximum length of a mode name is %u characters.\n",
  327.                    sizeof(cpicinit->mode_name)-1);
  328.             write_error(
  329.                    "Mode name of %s will be used.\n", cpicinit->mode_name);
  330.         }
  331.     }
  332.  
  333.     return rc;
  334. }
  335.  
  336.  
  337. /*
  338.  * The major difference between the default calls above and the set calls
  339.  * below is the setting of a flag in the set calls indicating that the user
  340.  * has specified this value.  This flag is used later as an indication that
  341.  * any value set by the symbolic destination name entries should be
  342.  * overridden.
  343.  */
  344.  
  345.  
  346. /******************************************************************************
  347.  *
  348.  *  cpicinit_set_tp_name
  349.  *
  350.  *  Returns:
  351.  *    CPICINIT_OK,     if there was no error.
  352.  *    CPICINIT_ERROR,  if there was an error.
  353.  *
  354.  *****************************************************************************/
  355. int
  356. cpicinit_set_tp_name(CPICINIT * cpicinit,
  357.                      char *     tp_name)
  358. {
  359.     cpicinit->set_tp_name = SET;
  360.     return cpicinit_default_tp_name(cpicinit, tp_name);
  361. }
  362.  
  363. /******************************************************************************
  364.  *
  365.  *  cpicinit_set_mode_name
  366.  *
  367.  *  Returns:
  368.  *    CPICINIT_OK,     if there was no error.
  369.  *    CPICINIT_ERROR,  if there was an error.
  370.  *
  371.  *****************************************************************************/
  372. int
  373. cpicinit_set_mode_name(CPICINIT * cpicinit,
  374.                        char *     mode_name)
  375. {
  376.     cpicinit->set_mode_name = SET;
  377.     return cpicinit_default_mode_name(cpicinit, mode_name);
  378. }
  379.  
  380. /******************************************************************************
  381.  *
  382.  *  cpicinit_set_destination
  383.  *
  384.  *  Returns:
  385.  *    CPICINIT_OK,     if there was no error.
  386.  *    CPICINIT_ERROR,  if there was an error.
  387.  *
  388.  *****************************************************************************/
  389. int
  390. cpicinit_set_destination(CPICINIT * cpicinit,
  391.                          char *     destination)
  392. {
  393.     int length;
  394.     int rc;
  395.  
  396.     cpicinit->set_destination = SET;
  397.  
  398.     length = strlen(destination);
  399.  
  400.     if (length < sizeof(cpicinit->destination)) {
  401.         rc = CPICINIT_ERROR;
  402.         memcpy(cpicinit->destination,
  403.                destination,
  404.                length);
  405.         cpicinit->destination[length] = '\0';
  406.     } else {
  407.         rc = CPICINIT_OK;
  408.         if (cpicinit -> show_error) {
  409.             write_error(
  410.                     "The destination you specified is too long:\n%s\n",
  411.                     destination);
  412.             write_error(
  413.             "The maximum length of a destination is %u characters.\n",
  414.                 sizeof(cpicinit->destination)-1);
  415.             write_error(
  416.                     "Destination %s will be used.\n", cpicinit->destination);
  417.         }
  418.     }
  419.  
  420.     return rc;
  421. }
  422.  
  423. /******************************************************************************
  424.  *
  425.  *  cpicinit_set_userid
  426.  *
  427.  *  Sets the userid to be used for security on the conversation.  Issuing
  428.  *  this call implies that the conversation will use security=PROGRAM;
  429.  *  a password will also be required in order to get a conversation.
  430.  *  The password should be set using either the cpicinit_set_password() call
  431.  *  or the cpicinit_get_password() call.
  432.  *
  433.  *  Returns:
  434.  *    CPICINIT_OK,     if there was no error.
  435.  *    CPICINIT_ERROR,  if there was an error.
  436.  *
  437.  *****************************************************************************/
  438. int
  439. cpicinit_set_userid(CPICINIT * cpicinit,
  440.                     char *     userid)
  441. /* initialize the userid */
  442. {
  443.     int length;
  444.     int rc;
  445.  
  446.     length = strlen(userid);
  447.  
  448.     if (length < sizeof(cpicinit->userid)) {
  449.         rc = CPICINIT_ERROR;
  450.         memcpy(cpicinit->userid,
  451.                userid,
  452.                length);
  453.         cpicinit->userid[length] = '\0';
  454.         cpicinit->set_userid = SET;
  455.         cpicinit->security_type = XC_SECURITY_PROGRAM;
  456.     } else {
  457.         rc = CPICINIT_OK;
  458.         if (cpicinit -> show_error) {
  459.             write_error(
  460.                     "The userid you specified is too long:\n%s\n",
  461.                     userid);
  462.             write_error(
  463.                    "The maximum length of a userid is %u characters.\n",
  464.                    sizeof(cpicinit->userid)-1);
  465.         }
  466.     }
  467.  
  468.     return rc;
  469.  
  470. }
  471. /******************************************************************************
  472.  *
  473.  *  cpicinit_query_password_needed
  474.  *
  475.  *  Can be used by the program to inquire whether a password will be required
  476.  *  to establish a conversation.  This can be used by a program instead of
  477.  *  keeping track itself of whether a userid has been specified.  If a password
  478.  *  is required, the password should be set using either the
  479.  *  cpicinit_set_password() call or the cpicinit_get_password() call.
  480.  *
  481.  *  Returns:
  482.  *    TRUE   if password is required
  483.  *    FALSE  if no password should be set
  484.  *
  485.  *****************************************************************************/
  486. int
  487. cpicinit_query_password_needed(CPICINIT * cpicinit)
  488. {
  489.     if (cpicinit->set_userid == SET && cpicinit->set_password == NOT_SET) {
  490.         return TRUE;
  491.     } else {
  492.         return FALSE;
  493.     }
  494. }
  495.  
  496.  
  497. /******************************************************************************
  498.  *
  499.  *  cpicinit_set_password
  500.  *
  501.  *  Sets the password to be used with security=PROGRAM.  This call should be
  502.  *  used in conjunction with the cpicinit_set_userid() call.
  503.  *
  504.  *  Returns:
  505.  *    CPICINIT_OK,     if there was no error.
  506.  *    CPICINIT_ERROR,  if there was an error.
  507.  *
  508.  *****************************************************************************/
  509. int
  510. cpicinit_set_password(CPICINIT * cpicinit,
  511.                     char *     password)
  512. /* initialize the password */
  513. {
  514.     int length;
  515.     int rc;
  516.  
  517.     length = strlen(password);
  518.  
  519.     if (length < sizeof(cpicinit->password)) {
  520.         rc = CPICINIT_ERROR;
  521.         memcpy(cpicinit->password,
  522.                password,
  523.                length);
  524.         cpicinit->password[length] = '\0';
  525.         cpicinit->set_password = SET;
  526.         cpicinit->security_type = XC_SECURITY_PROGRAM;
  527.     } else {
  528.         rc = CPICINIT_OK;
  529.         if (cpicinit -> show_error) {
  530.             write_error(
  531.                     "The password you specified is too long:\n%s\n",
  532.                     password);
  533.             write_error(
  534.                    "The maximum length of a password is %u characters.\n",
  535.                    sizeof(cpicinit->password)-1);
  536.         }
  537.     }
  538.  
  539.     return rc;
  540. }
  541.  
  542.  
  543. /******************************************************************************
  544.  *
  545.  *  cpicinit_get_password
  546.  *
  547.  *****************************************************************************/
  548. void
  549. cpicinit_get_password(CPICINIT * cpicinit)
  550. {
  551.     write_output("\nPassword: ");           /* display the prompt            */
  552.  
  553.     if (!get_password(cpicinit->password, sizeof(cpicinit->password)-1)) {
  554.         cpicinit->set_password = SET;
  555.         cpicinit->security_type = XC_SECURITY_PROGRAM;
  556.     }
  557.     return;
  558. }
  559.  
  560. /******************************************************************************
  561.  *
  562.  *  cpicinit_set_security_type
  563.  *
  564.  *****************************************************************************/
  565. void
  566. cpicinit_set_security_type(CPICINIT * cpicinit,
  567.                            unsigned long security_type)
  568. {
  569.     cpicinit->security_type = security_type;
  570. }
  571.  
  572.  
  573. /******************************************************************************
  574.  *
  575.  *  cpicinit_setup_conversation
  576.  *
  577.  *  The goal of this procedure is to initialize a CPI-C conversation ID
  578.  *  and make sure that partner destination information is all specified.
  579.  *  This destination information includes partner LU name, mode name,
  580.  *  and TP name.
  581.  *
  582.  *  To be as flexible as possible, the destination parameter can serve
  583.  *  a dual role.  If specified, the destination is first used as the
  584.  *  symbolic destination name.  If this does not produce a valid partner
  585.  *  LU name, another symbolic destination name will be used and the
  586.  *  destination parameter will be used instead as a partner LU name.
  587.  *
  588.  *  AN OVERVIEW OF THE PROCEDURE
  589.  *
  590.  *  If the destination was SET
  591.  *      use destination as a symbolic destination name
  592.  *      If CMINIT failed or there was no partner LU name extracted
  593.  *          use the default symbolic destination name or all blanks
  594.  *          use the destination as a partner LU name
  595.  *
  596.  *****************************************************************************/
  597. int
  598. cpicinit_setup_conversation(CPICINIT *      cpicinit,
  599.                             unsigned char * cm_conv_id,
  600.                             CPICERR *       cpicerr)
  601. {
  602.     CM_INT32 cm_rc = CM_OK;
  603.     CM_INT32 length;
  604.     int      dest_len;
  605.     char sym_dest_name[9];
  606.  
  607.     /* check if a destination was set by the cpicinit_set_destination() call */
  608.     if (cpicinit->set_destination == SET) {
  609.  
  610.         /* check if the destination could be a symbolic destination name     */
  611.         if (((dest_len = strlen(cpicinit->destination)) <
  612.                                                          MAX_SYM_DEST_NAME)) {
  613.             /*
  614.              * Try to use the specified destination as a symbolic
  615.              * destination name.  A symbolic destination name is blank
  616.              * padded and must contain all uppercase characters.
  617.              */
  618.  
  619.             memset(sym_dest_name,           /* Initialize the sym dest name  */
  620.                    ' ',                     /* to all blanks.                */
  621.                    sizeof(sym_dest_name));
  622.  
  623.             memcpy(sym_dest_name,           /* Copy the destination into the */
  624.                    cpicinit->destination,   /* sym dest name.                */
  625.                    dest_len);
  626.                                             /* place the null terminator     */
  627.             sym_dest_name[MAX_SYM_DEST_NAME - 1] = '\0';
  628.  
  629.             strupr(sym_dest_name);          /* sym dest must be uppercase    */
  630.  
  631.             /*
  632.              * Since we are using the destination as a sym_dest, make sure
  633.              * we don't also use it as a partner LU name.
  634.              */
  635.             cpicinit->set_destination = NOT_SET;
  636.  
  637.             cminit(cm_conv_id,
  638.                    (unsigned char *)sym_dest_name,
  639.                    &cm_rc);
  640.  
  641.         } else {
  642.             /*
  643.              * The destination was too long to be a symbolic destination name.
  644.              */
  645.         }
  646.  
  647.  
  648.  
  649.         if (cm_rc != CM_OK || !cpicinit_pln_valid(cm_conv_id)) {
  650.  
  651.             /*
  652.              * Since the destination was not a sym_dest, we can use it
  653.              * later as a partner LU name.
  654.              */
  655.             cpicinit->set_destination = SET;
  656.  
  657.             /*
  658.              * Try to use the default symbolic destination name.  If
  659.              * configured, this symbolic destination can be used to
  660.              * initialize the partner LU name and mode name entries,
  661.              * or left blank.
  662.              */
  663.             cminit(cm_conv_id,
  664.                    (unsigned char *)cpicinit->def_sym_dest_name,
  665.                    &cm_rc);
  666.  
  667.             if (cm_rc != CM_OK) {
  668.                 /*
  669.                  * Nothing else worked, so let's try the blank symbolic
  670.                  * destination name.  All CPI-C values will be initialized
  671.                  * to non usable values.
  672.                  */
  673.                 cminit(cm_conv_id,
  674.                        (unsigned char *)BLANK_SYM_DEST_NAME,
  675.                        &cm_rc);
  676.                 if (cm_rc != CM_OK) {
  677.                     return cpicerr_handle_rc(cpicerr, MSG_CMINIT, cm_rc);
  678.                 }
  679.  
  680.                 /*
  681.                  * Since the blank symbolic destination name was used,
  682.                  * we must set the partner LU name and mode even if we
  683.                  * use the defaults.
  684.                  */
  685.                 cpicinit->set_destination = cpicinit->set_mode_name = SET;
  686.  
  687.             }
  688.  
  689.         }
  690.  
  691.     } else {
  692.         /*
  693.          * Although no destination was specified, we can try to continue
  694.          * by using the default symbolic destination name.  If this entry
  695.          * is configured with a valid partner LU, we may be able to
  696.          * establish a connection with a partner.
  697.          */
  698.         cminit(cm_conv_id,
  699.                (unsigned char * )cpicinit->def_sym_dest_name,
  700.                &cm_rc);
  701.         if (cm_rc != CM_OK) {
  702.             /*
  703.              * Fill in conversation information for CPI-C error reporting.
  704.              */
  705.             cpicerr_set_conv_id(cpicerr, cm_conv_id);
  706.             return cpicerr_handle_rc(cpicerr, MSG_CMINIT, cm_rc);
  707.         }
  708.     }
  709.  
  710.     /*
  711.      * Fill in conversation information for CPI-C error reporting.
  712.      */
  713.     cpicerr_set_conv_id(cpicerr, cm_conv_id);
  714.  
  715.     if (cpicinit->set_destination == SET) {
  716.         CM_INT32 dest_length;
  717.         dest_length = strlen(cpicinit->destination);
  718.  
  719. #if defined(PLN_COULD_REQUIRE_LOWERCASE)
  720.         /*
  721.          * strupr should only be performed if the partner LU name is
  722.          * a fully qualified name.
  723.          */
  724. #ifdef FAPI
  725.         if ((strchr(cpicinit->destination,'.') != NULL) ||
  726.             (get_machine_mode() == 0)) {
  727.             strupr(cpicinit->destination);
  728.         }
  729. #else
  730.         if (strchr(cpicinit->destination,'.') != NULL) {
  731.             strupr(cpicinit->destination);
  732.         }
  733. #endif
  734. #else
  735.         strupr(cpicinit->destination);
  736. #endif
  737.  
  738.         cmspln(cm_conv_id,                  /* Set partner LU name           */
  739.                (unsigned char *)cpicinit->destination,
  740.                &dest_length,
  741.                &cm_rc);
  742.         if (cm_rc != CM_OK)
  743.             return cpicerr_handle_rc(cpicerr, MSG_CMSPLN, cm_rc);
  744.     }
  745.  
  746.     /*
  747.      * Since there is no way to query the TP name, we will always set it.
  748.      * The default TP name can be overridden on the cpicinit_set_tp_name
  749.      * call.
  750.      */
  751.  
  752.     length = strlen(cpicinit->tp_name);
  753.     cmstpn(cm_conv_id,                      /* Set TP name                   */
  754.            (unsigned char *)cpicinit->tp_name,
  755.            &length,
  756.            &cm_rc);
  757.     if (cm_rc != CM_OK)
  758.         return cpicerr_handle_rc(cpicerr, MSG_CMSTPN, cm_rc);
  759.  
  760.     /*
  761.      * If there was a cpicinit_set_mode_name call made previously or
  762.      * present mode name is not initialized, we need to set the mode
  763.      * name.
  764.      */
  765.     if ((cpicinit->set_mode_name == SET) ||
  766.                                          !cpicinit_mode_valid(cm_conv_id)) {
  767.         length = strlen(cpicinit->mode_name);
  768.         cmsmn(cm_conv_id,                   /* Set mode name                 */
  769.               (unsigned char *)cpicinit->mode_name,
  770.               &length,
  771.               &cm_rc);
  772.         if (cm_rc != CM_OK)
  773.             return cpicerr_handle_rc(cpicerr, MSG_CMSMN, cm_rc);
  774.     }
  775.  
  776. #if defined(SUPPORTS_SETTING_SECURITY)
  777.     /*
  778.      * If there was a cpicinit_set_userid AND cpicinit_set_password call made
  779.      * previously, we need to set the security parameters.  The security
  780.      * functions are not available on all CPI-C platforms.
  781.      */
  782.  
  783.     if (cpicinit->security_type == XC_SECURITY_NONE) {
  784.         CM_INT32 security_type;
  785.         security_type = XC_SECURITY_NONE;
  786.         xcscst(cm_conv_id,                  /* Set Security Type             */
  787.                &security_type,
  788.                &cm_rc);
  789.         if (cm_rc != CM_OK)
  790.             return cpicerr_handle_rc(cpicerr, MSG_XCSCST, cm_rc);
  791.     } else {
  792.         if ((cpicinit->set_userid == SET) && (cpicinit->set_password == SET)) {
  793.             CM_INT32 security_type;
  794.             security_type = XC_SECURITY_PROGRAM;
  795.             xcscst(cm_conv_id,              /* Set Security Type             */
  796.                    &security_type,
  797.                    &cm_rc);
  798.             if (cm_rc != CM_OK)
  799.                 return cpicerr_handle_rc(cpicerr, MSG_XCSCST, cm_rc);
  800.  
  801.             length = strlen(cpicinit->userid);
  802.             xcscsu(cm_conv_id,              /* Set Security Userid           */
  803.                    (unsigned char *)cpicinit->userid,
  804.                    &length,
  805.                    &cm_rc);
  806.             if (cm_rc != CM_OK)
  807.                 return cpicerr_handle_rc(cpicerr, MSG_XCSCSU, cm_rc);
  808.  
  809.             length = strlen(cpicinit->password);
  810.             xcscsp(cm_conv_id,              /* Set Security Password         */
  811.                    (unsigned char *)cpicinit->password,
  812.                    &length,
  813.                    &cm_rc);
  814.             if (cm_rc != CM_OK)
  815.                 return cpicerr_handle_rc(cpicerr, MSG_XCSCSP, cm_rc);
  816.  
  817.         }
  818.     }
  819.  
  820. #endif
  821.  
  822.     return FALSE;
  823. }
  824.  
  825.  
  826. /******************************************************************************
  827.  *
  828.  *  cpicinit_destroy
  829.  *
  830.  *  This function is the inverse of the cpicinit_new() call.  All memory
  831.  *  allocated by cpicinit_new() is freed.
  832.  *
  833.  *  This function has no return code.
  834.  *
  835.  *****************************************************************************/
  836. void
  837. cpicinit_destroy(CPICINIT * cpicinit)
  838. {
  839.     free(cpicinit);
  840.     return;
  841. }
  842.  
  843. /******************************************************************************
  844.  *
  845.  *  cpicinit_pln_valid
  846.  *
  847.  *  Internal function, used by cpic_setup_conversation().
  848.  *
  849.  *  This function is used after a cminit() call to ensure that there was
  850.  *  a partner LU name configured with the symbolic destination used on
  851.  *  cminit().  If there was no partner LU name configured with the symbolic
  852.  *  destination name, a partner LU name will have to be set with the cmspln()
  853.  *  call.
  854.  *
  855.  *  Returns:
  856.  *    TRUE  if a partner LU name was configured
  857.  *    FALSE is there was no partner LU name configured
  858.  *
  859.  *****************************************************************************/
  860. int
  861. cpicinit_pln_valid(unsigned char * cm_conv_id)
  862. {
  863.     unsigned char  destination[MAX_DESTINATION]; /* variable to store the    */
  864.                                             /* extracted partner LU name     */
  865.     CM_INT32       length = 0;              /* length of partner LU name     */
  866.     CM_RETURN_CODE cm_rc;                   /* CPI-C return code             */
  867.     int            rc;                      /* procedure return code         */
  868.  
  869.     cmepln(cm_conv_id,                      /* extract partner LU name       */
  870.            destination,
  871.            &length,                         /* length of partner LU name     */
  872.            &cm_rc );
  873.  
  874.     if (cm_rc != CM_OK || (length == 1 && destination[0] == ' ')) {
  875.         rc = FALSE;
  876.     } else {
  877.         rc = TRUE;
  878.     }
  879.     return rc;
  880. }
  881.  
  882. /******************************************************************************
  883.  *
  884.  *  cpicinit_mode_valid
  885.  *
  886.  *  Internal function, used by cpic_setup_conversation().
  887.  *
  888.  *  This function is used after a cminit() call to ensure that there was
  889.  *  a mode name configured with the symbolic destination used on  cminit().
  890.  *  If there was no mode name configured with the symbolic destination name,
  891.  *  a partner LU name will have to be set with the cmsmn() call.
  892.  *
  893.  *  Returns:
  894.  *    TRUE  if a mode name was configured
  895.  *    FALSE is there was no mode name configured
  896.  *
  897.  *****************************************************************************/
  898. cpicinit_mode_valid(unsigned char * cm_conv_id)
  899. {
  900.     unsigned char  mode[MAX_MODE_NAME];     /* variable to store the         */
  901.                                             /* extracted mode name           */
  902.     CM_INT32       length = 0;              /* length of mode name           */
  903.     CM_RETURN_CODE cm_rc;                   /* CPI-C return code             */
  904.     int            rc;                      /* procedure return code         */
  905.  
  906.     cmemn(cm_conv_id,                       /* extract mode name             */
  907.           mode,
  908.           &length,
  909.           &cm_rc );
  910.  
  911.     if (cm_rc != CM_OK || length == 0) {
  912.         rc = FALSE;
  913.     } else {
  914.         rc = TRUE;
  915.     }
  916.     return rc;
  917.  
  918. }
  919.  
  920.