root/opal/mca/pmix/pmix4x/pmix/src/mca/base/pmix_mca_base_var.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pmix_mca_base_var_source_file
  2. pmix_mca_base_var_generate_full_name4
  3. compare_strings
  4. append_filename_to_list
  5. pmix_mca_base_var_init
  6. process_env_list
  7. pmix_mca_base_var_process_env_list
  8. pmix_mca_base_var_process_env_list_from_file
  9. resolve_relative_paths
  10. pmix_mca_base_var_cache_files
  11. pmix_mca_base_var_get_value
  12. var_set_string
  13. int_from_string
  14. var_set_from_string
  15. pmix_mca_base_var_set_value
  16. pmix_mca_base_var_deregister
  17. var_get
  18. pmix_mca_base_var_env_name
  19. var_find_by_name
  20. var_find
  21. pmix_mca_base_var_find
  22. pmix_mca_base_var_find_by_name
  23. pmix_mca_base_var_set_flag
  24. pmix_mca_base_var_get
  25. pmix_mca_base_var_build_env
  26. pmix_mca_base_var_finalize
  27. fixup_files
  28. read_files
  29. register_variable
  30. pmix_mca_base_var_register
  31. pmix_mca_base_component_var_register
  32. pmix_mca_base_framework_var_register
  33. pmix_mca_base_var_register_synonym
  34. var_get_env
  35. var_set_from_env
  36. var_set_from_file
  37. var_set_initial
  38. var_constructor
  39. var_destructor
  40. fv_constructor
  41. fv_destructor
  42. source_name
  43. var_value_string
  44. pmix_mca_base_var_check_exclusive
  45. pmix_mca_base_var_get_count
  46. pmix_mca_base_var_dump

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2004-2008 The Trustees of Indiana University and Indiana
   4  *                         University Research and Technology
   5  *                         Corporation.  All rights reserved.
   6  * Copyright (c) 2004-2012 The University of Tennessee and The University
   7  *                         of Tennessee Research Foundation.  All rights
   8  *                         reserved.
   9  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
  10  *                         University of Stuttgart.  All rights reserved.
  11  * Copyright (c) 2004-2005 The Regents of the University of California.
  12  *                         All rights reserved.
  13  * Copyright (c) 2008-2015 Cisco Systems, Inc.  All rights reserved.
  14  * Copyright (c) 2012-2015 Los Alamos National Security, LLC. All rights
  15  *                         reserved.
  16  * Copyright (c) 2014-2018 Intel, Inc. All rights reserved.
  17  * Copyright (c) 2015-2019 Research Organization for Information Science
  18  *                         and Technology (RIST).  All rights reserved.
  19  * $COPYRIGHT$
  20  *
  21  * Additional copyrights may follow
  22  *
  23  * $HEADER$
  24  */
  25 
  26 #include <src/include/pmix_config.h>
  27 
  28 #include <stdio.h>
  29 #include <string.h>
  30 #include <stdlib.h>
  31 #ifdef HAVE_UNISTD_H
  32 #include <unistd.h>
  33 #endif
  34 #ifdef HAVE_SYS_PARAM_H
  35 #include <sys/param.h>
  36 #endif
  37 #include <errno.h>
  38 
  39 #include "src/include/pmix_stdint.h"
  40 #include "src/mca/pinstalldirs/pinstalldirs.h"
  41 #include "src/util/os_path.h"
  42 #include "src/util/path.h"
  43 #include "src/util/show_help.h"
  44 #include "src/util/printf.h"
  45 #include "src/util/argv.h"
  46 #include "src/util/error.h"
  47 #include "src/mca/mca.h"
  48 #include "src/mca/base/pmix_mca_base_vari.h"
  49 #include "pmix_common.h"
  50 #include "src/util/output.h"
  51 #include "src/util/pmix_environ.h"
  52 
  53 /*
  54  * local variables
  55  */
  56 static pmix_pointer_array_t pmix_mca_base_vars;
  57 static const char *mca_prefix = "PMIX_MCA_";
  58 static char *home = NULL;
  59 static char *cwd  = NULL;
  60 bool pmix_mca_base_var_initialized = false;
  61 static char * force_agg_path = NULL;
  62 static char *pmix_mca_base_var_files = NULL;
  63 static char *pmix_mca_base_envar_files = NULL;
  64 static char **pmix_mca_base_var_file_list = NULL;
  65 static char *pmix_mca_base_var_override_file = NULL;
  66 static char *pmix_mca_base_var_file_prefix = NULL;
  67 static char *pmix_mca_base_envar_file_prefix = NULL;
  68 static char *pmix_mca_base_param_file_path = NULL;
  69 static char *pmix_mca_base_env_list = NULL;
  70 #define PMIX_MCA_BASE_ENV_LIST_SEP_DEFAULT ";"
  71 static char *pmix_mca_base_env_list_sep = PMIX_MCA_BASE_ENV_LIST_SEP_DEFAULT;
  72 static char *pmix_mca_base_env_list_internal = NULL;
  73 static bool pmix_mca_base_var_suppress_override_warning = false;
  74 static pmix_list_t pmix_mca_base_var_file_values;
  75 static pmix_list_t pmix_mca_base_envar_file_values;
  76 static pmix_list_t pmix_mca_base_var_override_values;
  77 
  78 static int pmix_mca_base_var_count = 0;
  79 
  80 static pmix_hash_table_t pmix_mca_base_var_index_hash;
  81 
  82 const char *pmix_var_type_names[] = {
  83     "int",
  84     "unsigned_int",
  85     "unsigned_long",
  86     "unsigned_long_long",
  87     "size_t",
  88     "string",
  89     "version_string",
  90     "bool",
  91     "double"
  92 };
  93 
  94 const size_t pmix_var_type_sizes[] = {
  95     sizeof (int),
  96     sizeof (unsigned),
  97     sizeof (unsigned long),
  98     sizeof (unsigned long long),
  99     sizeof (size_t),
 100     sizeof (char),
 101     sizeof (char),
 102     sizeof (bool),
 103     sizeof (double)
 104 };
 105 
 106 const char *pmix_var_source_names[] = {
 107     "default",
 108     "command line",
 109     "environment",
 110     "file",
 111     "set",
 112     "override"
 113 };
 114 
 115 
 116 static const char *info_lvl_strings[] = {
 117     "user/basic",
 118     "user/detail",
 119     "user/all",
 120     "tuner/basic",
 121     "tuner/detail",
 122     "tuner/all",
 123     "dev/basic",
 124     "dev/detail",
 125     "dev/all"
 126 };
 127 
 128 /*
 129  * local functions
 130  */
 131 static int fixup_files(char **file_list, char * path, bool rel_path_search, char sep);
 132 static int read_files (char *file_list, pmix_list_t *file_values, char sep);
 133 static int var_set_initial (pmix_mca_base_var_t *var, pmix_mca_base_var_t *original);
 134 static int var_get (int vari, pmix_mca_base_var_t **var_out, bool original);
 135 static int var_value_string (pmix_mca_base_var_t *var, char **value_string);
 136 
 137 /*
 138  * classes
 139  */
 140 static void var_constructor (pmix_mca_base_var_t *p);
 141 static void var_destructor (pmix_mca_base_var_t *p);
 142 PMIX_CLASS_INSTANCE(pmix_mca_base_var_t, pmix_object_t,
 143                    var_constructor, var_destructor);
 144 
 145 static void fv_constructor (pmix_mca_base_var_file_value_t *p);
 146 static void fv_destructor (pmix_mca_base_var_file_value_t *p);
 147 PMIX_CLASS_INSTANCE(pmix_mca_base_var_file_value_t, pmix_list_item_t,
 148                    fv_constructor, fv_destructor);
 149 
 150 static const char *pmix_mca_base_var_source_file (const pmix_mca_base_var_t *var)
 151 {
 152     pmix_mca_base_var_file_value_t *fv = (pmix_mca_base_var_file_value_t *) var->mbv_file_value;
 153 
 154     if (NULL != var->mbv_source_file) {
 155         return var->mbv_source_file;
 156     }
 157 
 158     if (fv) {
 159         return fv->mbvfv_file;
 160     }
 161 
 162     return NULL;
 163 }
 164 
 165 /*
 166  * Generate a full name from three names
 167  */
 168 int pmix_mca_base_var_generate_full_name4 (const char *project, const char *framework, const char *component,
 169                                       const char *variable, char **full_name)
 170 {
 171     const char * const names[] = {project, framework, component, variable};
 172     char *name, *tmp;
 173     size_t i, len;
 174 
 175     *full_name = NULL;
 176 
 177     for (i = 0, len = 0 ; i < 4 ; ++i) {
 178         if (NULL != names[i]) {
 179             /* Add space for the string + _ or \0 */
 180             len += strlen (names[i]) + 1;
 181         }
 182     }
 183 
 184     name = calloc (1, len);
 185     if (NULL == name) {
 186         return PMIX_ERR_OUT_OF_RESOURCE;
 187     }
 188 
 189     for (i = 0, tmp = name ; i < 4 ; ++i) {
 190         if (NULL != names[i]) {
 191             if (name != tmp) {
 192                 *tmp++ = '_';
 193             }
 194             strncat (name, names[i], len - (size_t)(uintptr_t)(tmp - name));
 195             tmp += strlen (names[i]);
 196         }
 197     }
 198 
 199     *full_name = name;
 200     return PMIX_SUCCESS;
 201 }
 202 
 203 static int compare_strings (const char *str1, const char *str2) {
 204     if ((NULL != str1 && 0 == strcmp (str1, "*")) ||
 205         (NULL == str1 && NULL == str2)) {
 206         return 0;
 207     }
 208 
 209     if (NULL != str1 && NULL != str2) {
 210         return strcmp (str1, str2);
 211     }
 212 
 213     return 1;
 214 }
 215 
 216 /*
 217  * Append a filename to the file list if it does not exist and return a
 218  * pointer to the filename in the list.
 219  */
 220 static char *append_filename_to_list(const char *filename)
 221 {
 222     int i, count;
 223 
 224     (void) pmix_argv_append_unique_nosize(&pmix_mca_base_var_file_list, filename);
 225 
 226     count = pmix_argv_count(pmix_mca_base_var_file_list);
 227 
 228     for (i = count - 1; i >= 0; --i) {
 229         if (0 == strcmp (pmix_mca_base_var_file_list[i], filename)) {
 230             return pmix_mca_base_var_file_list[i];
 231         }
 232     }
 233 
 234     /* *#@*? */
 235     return NULL;
 236 }
 237 
 238 /*
 239  * Set it up
 240  */
 241 int pmix_mca_base_var_init(void)
 242 {
 243     int ret;
 244     char *name = NULL;
 245 
 246     if (!pmix_mca_base_var_initialized) {
 247         /* Init the value array for the param storage */
 248 
 249         PMIX_CONSTRUCT(&pmix_mca_base_vars, pmix_pointer_array_t);
 250         /* These values are arbitrary */
 251         ret = pmix_pointer_array_init (&pmix_mca_base_vars, 128, 16384, 128);
 252         if (PMIX_SUCCESS != ret) {
 253             return ret;
 254         }
 255 
 256         pmix_mca_base_var_count = 0;
 257 
 258         /* Init the file param value list */
 259 
 260         PMIX_CONSTRUCT(&pmix_mca_base_var_file_values, pmix_list_t);
 261         PMIX_CONSTRUCT(&pmix_mca_base_envar_file_values, pmix_list_t);
 262         PMIX_CONSTRUCT(&pmix_mca_base_var_override_values, pmix_list_t);
 263         PMIX_CONSTRUCT(&pmix_mca_base_var_index_hash, pmix_hash_table_t);
 264 
 265         ret = pmix_hash_table_init (&pmix_mca_base_var_index_hash, 1024);
 266         if (PMIX_SUCCESS != ret) {
 267             return ret;
 268         }
 269 
 270         ret = pmix_mca_base_var_group_init ();
 271         if  (PMIX_SUCCESS != ret) {
 272             return ret;
 273         }
 274 
 275         /* Set this before we register the parameter, below */
 276 
 277         pmix_mca_base_var_initialized = true;
 278 
 279         pmix_mca_base_var_cache_files(false);
 280 
 281         /* register the envar-forwarding params */
 282         (void)pmix_mca_base_var_register ("pmix", "mca", "base", "env_list",
 283                                      "Set SHELL env variables",
 284                                      PMIX_MCA_BASE_VAR_TYPE_STRING, NULL, 0, 0, PMIX_INFO_LVL_3,
 285                                      PMIX_MCA_BASE_VAR_SCOPE_READONLY, &pmix_mca_base_env_list);
 286 
 287         pmix_mca_base_env_list_sep = PMIX_MCA_BASE_ENV_LIST_SEP_DEFAULT;
 288         (void)pmix_mca_base_var_register ("pmix", "mca", "base", "env_list_delimiter",
 289                                      "Set SHELL env variables delimiter. Default: semicolon ';'",
 290                                      PMIX_MCA_BASE_VAR_TYPE_STRING, NULL, 0, 0, PMIX_INFO_LVL_3,
 291                                      PMIX_MCA_BASE_VAR_SCOPE_READONLY, &pmix_mca_base_env_list_sep);
 292 
 293         /* Set OMPI_MCA_pmix_mca_base_env_list variable, it might not be set before
 294          * if mca variable was taken from amca conf file. Need to set it
 295          * here because pmix_mca_base_var_process_env_list is called from schizo_ompi.c
 296          * only when this env variable was set.
 297          */
 298         if (NULL != pmix_mca_base_env_list) {
 299             (void) pmix_mca_base_var_env_name ("pmix_mca_base_env_list", &name);
 300             if (NULL != name) {
 301                 pmix_setenv(name, pmix_mca_base_env_list, false, &environ);
 302                 free(name);
 303             }
 304         }
 305 
 306         /* Register internal MCA variable pmix_mca_base_env_list_internal. It can be set only during
 307          * parsing of amca conf file and contains SHELL env variables specified via -x there.
 308          * Its format is the same as for pmix_mca_base_env_list.
 309          */
 310         (void)pmix_mca_base_var_register ("pmix", "mca", "base", "env_list_internal",
 311                 "Store SHELL env variables from amca conf file",
 312                 PMIX_MCA_BASE_VAR_TYPE_STRING, NULL, 0, PMIX_MCA_BASE_VAR_FLAG_INTERNAL, PMIX_INFO_LVL_3,
 313                 PMIX_MCA_BASE_VAR_SCOPE_READONLY, &pmix_mca_base_env_list_internal);
 314     }
 315 
 316     return PMIX_SUCCESS;
 317 }
 318 
 319 static void process_env_list(char *env_list, char ***argv, char sep)
 320 {
 321     char** tokens;
 322     char *ptr, *value;
 323 
 324     tokens = pmix_argv_split(env_list, (int)sep);
 325     if (NULL == tokens) {
 326         return;
 327     }
 328 
 329     for (int i = 0 ; NULL != tokens[i] ; ++i) {
 330         if (NULL == (ptr = strchr(tokens[i], '='))) {
 331             value = getenv(tokens[i]);
 332             if (NULL == value) {
 333                 pmix_show_help("help-pmix-mca-var.txt", "incorrect-env-list-param",
 334                                true, tokens[i], env_list);
 335                 break;
 336             }
 337 
 338             /* duplicate the value to silence tainted string coverity issue */
 339             value = strdup (value);
 340             if (NULL == value) {
 341                 /* out of memory */
 342                 break;
 343             }
 344 
 345             if (NULL != (ptr = strchr(value, '='))) {
 346                 *ptr = '\0';
 347                 pmix_setenv(value, ptr + 1, true, argv);
 348             } else {
 349                 pmix_setenv(tokens[i], value, true, argv);
 350             }
 351 
 352             free (value);
 353         } else {
 354             *ptr = '\0';
 355             pmix_setenv(tokens[i], ptr + 1, true, argv);
 356             /* NTH: don't bother resetting ptr to = since the string will not be used again */
 357         }
 358     }
 359 
 360     pmix_argv_free(tokens);
 361 }
 362 
 363 int pmix_mca_base_var_process_env_list(char ***argv)
 364 {
 365     char sep;
 366     sep = ';';
 367     if (NULL != pmix_mca_base_env_list_sep) {
 368         if (1 == strlen(pmix_mca_base_env_list_sep)) {
 369             sep = pmix_mca_base_env_list_sep[0];
 370         } else {
 371             pmix_show_help("help-pmix-mca-var.txt", "incorrect-env-list-sep",
 372                     true, pmix_mca_base_env_list_sep);
 373             return PMIX_SUCCESS;
 374         }
 375     }
 376     if (NULL != pmix_mca_base_env_list) {
 377         process_env_list(pmix_mca_base_env_list, argv, sep);
 378     }
 379 
 380     return PMIX_SUCCESS;
 381 }
 382 
 383 int pmix_mca_base_var_process_env_list_from_file(char ***argv)
 384 {
 385     if (NULL != pmix_mca_base_env_list_internal) {
 386         process_env_list(pmix_mca_base_env_list_internal, argv, ';');
 387     }
 388     return PMIX_SUCCESS;
 389 }
 390 
 391 static void resolve_relative_paths(char **file_prefix, char *file_path, bool rel_path_search, char **files, char sep)
 392 {
 393     char *tmp_str;
 394     /*
 395      * Resolve all relative paths.
 396      * the file list returned will contain only absolute paths
 397      */
 398     if( PMIX_SUCCESS != fixup_files(file_prefix, file_path, rel_path_search, sep) ) {
 399 #if 0
 400         /* JJH We need to die! */
 401         abort();
 402 #else
 403         ;
 404 #endif
 405     }
 406     else {
 407         /* Prepend the files to the search list */
 408         if (0 > asprintf(&tmp_str, "%s%c%s", *file_prefix, sep, *files)) {
 409             pmix_output(0, "OUT OF MEM");
 410             free(*files);
 411             free(tmp_str);
 412             *files = NULL;
 413             return;
 414         }
 415         free (*files);
 416         *files = tmp_str;
 417     }
 418 }
 419 
 420 int pmix_mca_base_var_cache_files(bool rel_path_search)
 421 {
 422     char *tmp;
 423     int ret;
 424 
 425     /* We may need this later */
 426     home = (char*)pmix_home_directory();
 427 
 428     if(NULL == cwd) {
 429         cwd = (char *) malloc(sizeof(char) * MAXPATHLEN);
 430         if( NULL == (cwd = getcwd(cwd, MAXPATHLEN) )) {
 431             pmix_output(0, "Error: Unable to get the current working directory\n");
 432             cwd = strdup(".");
 433         }
 434     }
 435 
 436 #if PMIX_WANT_HOME_CONFIG_FILES
 437     ret = asprintf(&pmix_mca_base_var_files, "%s"PMIX_PATH_SEP".pmix" PMIX_PATH_SEP
 438                    "mca-params.conf%c%s" PMIX_PATH_SEP "pmix-mca-params.conf",
 439                    home, ',', pmix_pinstall_dirs.sysconfdir);
 440 #else
 441     ret = asprintf(&pmix_mca_base_var_files, "%s" PMIX_PATH_SEP "pmix-mca-params.conf",
 442                    pmix_pinstall_dirs.sysconfdir);
 443 #endif
 444     if (0 > ret) {
 445         return PMIX_ERR_OUT_OF_RESOURCE;
 446     }
 447 
 448     /* Initialize a parameter that says where MCA param files can be found.
 449        We may change this value so set the scope to PMIX_MCA_BASE_VAR_SCOPE_READONLY */
 450     tmp = pmix_mca_base_var_files;
 451     ret = pmix_mca_base_var_register ("pmix", "mca", "base", "param_files", "Path for MCA "
 452                                  "configuration files containing variable values",
 453                                  PMIX_MCA_BASE_VAR_TYPE_STRING, NULL, 0, 0, PMIX_INFO_LVL_2,
 454                                  PMIX_MCA_BASE_VAR_SCOPE_READONLY, &pmix_mca_base_var_files);
 455     free (tmp);
 456     if (PMIX_SUCCESS != ret) {
 457         return ret;
 458     }
 459 
 460     pmix_mca_base_envar_files = strdup(pmix_mca_base_var_files);
 461 
 462     (void) pmix_mca_base_var_register_synonym (ret, "pmix", "mca", NULL, "param_files",
 463                                           PMIX_MCA_BASE_VAR_SYN_FLAG_DEPRECATED);
 464 
 465     ret = asprintf(&pmix_mca_base_var_override_file, "%s" PMIX_PATH_SEP "pmix-mca-params-override.conf",
 466                    pmix_pinstall_dirs.sysconfdir);
 467     if (0 > ret) {
 468         return PMIX_ERR_OUT_OF_RESOURCE;
 469     }
 470 
 471     tmp = pmix_mca_base_var_override_file;
 472     ret = pmix_mca_base_var_register ("pmix", "mca", "base", "override_param_file",
 473                                  "Variables set in this file will override any value set in"
 474                                  "the environment or another configuration file",
 475                                  PMIX_MCA_BASE_VAR_TYPE_STRING, NULL, 0, PMIX_MCA_BASE_VAR_FLAG_DEFAULT_ONLY,
 476                                  PMIX_INFO_LVL_2, PMIX_MCA_BASE_VAR_SCOPE_CONSTANT,
 477                                  &pmix_mca_base_var_override_file);
 478     free (tmp);
 479     if (0 > ret) {
 480         return ret;
 481     }
 482 
 483     /* Disable reading MCA parameter files. */
 484     if (0 == strcmp (pmix_mca_base_var_files, "none")) {
 485         return PMIX_SUCCESS;
 486     }
 487 
 488     pmix_mca_base_var_suppress_override_warning = false;
 489     ret = pmix_mca_base_var_register ("pmix", "mca", "base", "suppress_override_warning",
 490                                  "Suppress warnings when attempting to set an overridden value (default: false)",
 491                                  PMIX_MCA_BASE_VAR_TYPE_BOOL, NULL, 0, 0, PMIX_INFO_LVL_2,
 492                                  PMIX_MCA_BASE_VAR_SCOPE_LOCAL, &pmix_mca_base_var_suppress_override_warning);
 493     if (0 > ret) {
 494         return ret;
 495     }
 496 
 497     /* Aggregate MCA parameter files
 498      * A prefix search path to look up aggregate MCA parameter file
 499      * requests that do not specify an absolute path
 500      */
 501     pmix_mca_base_var_file_prefix = NULL;
 502     ret = pmix_mca_base_var_register ("pmix", "mca", "base", "param_file_prefix",
 503                                  "Aggregate MCA parameter file sets",
 504                                  PMIX_MCA_BASE_VAR_TYPE_STRING, NULL, 0, 0, PMIX_INFO_LVL_3,
 505                                  PMIX_MCA_BASE_VAR_SCOPE_READONLY, &pmix_mca_base_var_file_prefix);
 506     if (0 > ret) {
 507         return ret;
 508     }
 509 
 510     pmix_mca_base_envar_file_prefix = NULL;
 511     ret = pmix_mca_base_var_register ("pmix", "mca", "base", "envar_file_prefix",
 512                                  "Aggregate MCA parameter file set for env variables",
 513                                  PMIX_MCA_BASE_VAR_TYPE_STRING, NULL, 0, 0, PMIX_INFO_LVL_3,
 514                                  PMIX_MCA_BASE_VAR_SCOPE_READONLY, &pmix_mca_base_envar_file_prefix);
 515     if (0 > ret) {
 516         return ret;
 517     }
 518 
 519     ret = asprintf(&pmix_mca_base_param_file_path, "%s" PMIX_PATH_SEP "amca-param-sets%c%s",
 520                    pmix_pinstall_dirs.pmixdatadir, PMIX_ENV_SEP, cwd);
 521     if (0 > ret) {
 522         return PMIX_ERR_OUT_OF_RESOURCE;
 523     }
 524 
 525     tmp = pmix_mca_base_param_file_path;
 526     ret = pmix_mca_base_var_register ("pmix", "mca", "base", "param_file_path",
 527                                  "Aggregate MCA parameter Search path",
 528                                  PMIX_MCA_BASE_VAR_TYPE_STRING, NULL, 0, 0, PMIX_INFO_LVL_3,
 529                                  PMIX_MCA_BASE_VAR_SCOPE_READONLY, &pmix_mca_base_param_file_path);
 530     free (tmp);
 531     if (0 > ret) {
 532         return ret;
 533     }
 534 
 535     force_agg_path = NULL;
 536     ret = pmix_mca_base_var_register ("pmix", "mca", "base", "param_file_path_force",
 537                                  "Forced Aggregate MCA parameter Search path",
 538                                  PMIX_MCA_BASE_VAR_TYPE_STRING, NULL, 0, 0, PMIX_INFO_LVL_3,
 539                                  PMIX_MCA_BASE_VAR_SCOPE_READONLY, &force_agg_path);
 540     if (0 > ret) {
 541         return ret;
 542     }
 543 
 544     if (NULL != force_agg_path) {
 545         if (NULL != pmix_mca_base_param_file_path) {
 546             char *tmp_str = pmix_mca_base_param_file_path;
 547 
 548             ret = asprintf(&pmix_mca_base_param_file_path, "%s%c%s", force_agg_path, PMIX_ENV_SEP, tmp_str);
 549             free(tmp_str);
 550             if (0 > ret) {
 551                 return PMIX_ERR_OUT_OF_RESOURCE;
 552             }
 553         } else {
 554             pmix_mca_base_param_file_path = strdup(force_agg_path);
 555         }
 556     }
 557 
 558     if (NULL != pmix_mca_base_var_file_prefix) {
 559        resolve_relative_paths(&pmix_mca_base_var_file_prefix, pmix_mca_base_param_file_path, rel_path_search, &pmix_mca_base_var_files, PMIX_ENV_SEP);
 560     }
 561     read_files (pmix_mca_base_var_files, &pmix_mca_base_var_file_values, ',');
 562 
 563     if (NULL != pmix_mca_base_envar_file_prefix) {
 564        resolve_relative_paths(&pmix_mca_base_envar_file_prefix, pmix_mca_base_param_file_path, rel_path_search, &pmix_mca_base_envar_files, ',');
 565     }
 566     read_files (pmix_mca_base_envar_files, &pmix_mca_base_envar_file_values, ',');
 567 
 568     if (0 == access(pmix_mca_base_var_override_file, F_OK)) {
 569         read_files (pmix_mca_base_var_override_file, &pmix_mca_base_var_override_values, PMIX_ENV_SEP);
 570     }
 571 
 572     return PMIX_SUCCESS;
 573 }
 574 
 575 /*
 576  * Look up an integer MCA parameter.
 577  */
 578 int pmix_mca_base_var_get_value (int vari, void *value,
 579                             pmix_mca_base_var_source_t *source,
 580                             const char **source_file)
 581 {
 582     pmix_mca_base_var_t *var;
 583     void **tmp = (void **) value;
 584     int ret;
 585 
 586     ret = var_get (vari, &var, true);
 587     if (PMIX_SUCCESS != ret) {
 588         return ret;
 589     }
 590 
 591     if (!PMIX_VAR_IS_VALID(var[0])) {
 592         return PMIX_ERR_NOT_FOUND;
 593     }
 594 
 595     if (NULL != value) {
 596         /* Return a poiner to our backing store (either a char **, int *,
 597            or bool *) */
 598         *tmp = var->mbv_storage;
 599     }
 600 
 601     if (NULL != source) {
 602         *source = var->mbv_source;
 603     }
 604 
 605     if (NULL != source_file) {
 606         *source_file = pmix_mca_base_var_source_file (var);
 607     }
 608 
 609     return PMIX_SUCCESS;
 610 }
 611 
 612 static int var_set_string (pmix_mca_base_var_t *var, char *value)
 613 {
 614     char *tmp;
 615     int ret;
 616 
 617     if (NULL != var->mbv_storage->stringval) {
 618         free (var->mbv_storage->stringval);
 619     }
 620 
 621     var->mbv_storage->stringval = NULL;
 622 
 623     if (NULL == value || 0 == strlen (value)) {
 624         return PMIX_SUCCESS;
 625     }
 626 
 627     /* Replace all instances of ~/ in a path-style string with the
 628        user's home directory. This may be handled by the enumerator
 629        in the future. */
 630     if (0 == strncmp (value, "~/", 2)) {
 631         if (NULL != home) {
 632             ret = asprintf (&value, "%s/%s", home, value + 2);
 633             if (0 > ret) {
 634                 return PMIX_ERROR;
 635             }
 636         } else {
 637             value = strdup (value + 2);
 638         }
 639     } else {
 640         value = strdup (value);
 641     }
 642 
 643     if (NULL == value) {
 644         return PMIX_ERR_OUT_OF_RESOURCE;
 645     }
 646 
 647     while (NULL != (tmp = strstr (value, ":~/"))) {
 648         tmp[0] = '\0';
 649         tmp += 3;
 650 
 651         ret = asprintf (&tmp, "%s:%s%s%s", value,
 652                         home ? home : "", home ? "/" : "", tmp);
 653 
 654         free (value);
 655 
 656         if (0 > ret) {
 657             return PMIX_ERR_OUT_OF_RESOURCE;
 658         }
 659 
 660         value = tmp;
 661     }
 662 
 663     var->mbv_storage->stringval = value;
 664 
 665     return PMIX_SUCCESS;
 666 }
 667 
 668 static int int_from_string(const char *src, pmix_mca_base_var_enum_t *enumerator, uint64_t *value_out)
 669 {
 670     uint64_t value;
 671     bool is_int;
 672     char *tmp;
 673 
 674     if (NULL == src || 0 == strlen (src)) {
 675         if (NULL == enumerator) {
 676             *value_out = 0;
 677         }
 678 
 679         return PMIX_SUCCESS;
 680     }
 681 
 682     if (enumerator) {
 683         int int_val, ret;
 684         ret = enumerator->value_from_string(enumerator, src, &int_val);
 685         if (PMIX_SUCCESS != ret) {
 686             return ret;
 687         }
 688         *value_out = (uint64_t) int_val;
 689 
 690         return PMIX_SUCCESS;
 691     }
 692 
 693     /* Check for an integer value */
 694     value = strtoull (src, &tmp, 0);
 695     if (tmp[0] == '\0') {
 696         is_int = true;
 697     } else {
 698         is_int = false;
 699     }
 700 
 701     if (!is_int && tmp != src) {
 702         switch (tmp[0]) {
 703         case 'G':
 704         case 'g':
 705             value <<= 30;
 706             break;
 707         case 'M':
 708         case 'm':
 709             value <<= 20;
 710             break;
 711         case 'K':
 712         case 'k':
 713             value <<= 10;
 714             break;
 715         default:
 716             break;
 717         }
 718     }
 719 
 720     *value_out = value;
 721 
 722     return PMIX_SUCCESS;
 723 }
 724 
 725 static int var_set_from_string (pmix_mca_base_var_t *var, char *src)
 726 {
 727     pmix_mca_base_var_storage_t *dst = var->mbv_storage;
 728     uint64_t int_value = 0;
 729     int ret;
 730 
 731     switch (var->mbv_type) {
 732     case PMIX_MCA_BASE_VAR_TYPE_INT:
 733     case PMIX_MCA_BASE_VAR_TYPE_UNSIGNED_INT:
 734     case PMIX_MCA_BASE_VAR_TYPE_UNSIGNED_LONG:
 735     case PMIX_MCA_BASE_VAR_TYPE_UNSIGNED_LONG_LONG:
 736     case PMIX_MCA_BASE_VAR_TYPE_BOOL:
 737     case PMIX_MCA_BASE_VAR_TYPE_SIZE_T:
 738         ret = int_from_string(src, var->mbv_enumerator, &int_value);
 739         if (PMIX_ERR_VALUE_OUT_OF_BOUNDS == ret ||
 740             (PMIX_MCA_BASE_VAR_TYPE_INT == var->mbv_type && ((int) int_value != (int64_t) int_value)) ||
 741             (PMIX_MCA_BASE_VAR_TYPE_UNSIGNED_INT == var->mbv_type && ((unsigned int) int_value != int_value))) {
 742             if (var->mbv_enumerator) {
 743                 char *valid_values;
 744                 (void) var->mbv_enumerator->dump(var->mbv_enumerator, &valid_values);
 745                 pmix_show_help("help-pmix-mca-var.txt", "invalid-value-enum",
 746                                true, var->mbv_full_name, src, valid_values);
 747                 free(valid_values);
 748             } else {
 749                 pmix_show_help("help-pmix-mca-var.txt", "invalid-value",
 750                                true, var->mbv_full_name, src);
 751             }
 752 
 753             return PMIX_ERR_VALUE_OUT_OF_BOUNDS;
 754         }
 755 
 756         if (PMIX_MCA_BASE_VAR_TYPE_INT == var->mbv_type ||
 757             PMIX_MCA_BASE_VAR_TYPE_UNSIGNED_INT == var->mbv_type) {
 758             int *castme = (int*) var->mbv_storage;
 759             *castme = int_value;
 760         } else if (PMIX_MCA_BASE_VAR_TYPE_UNSIGNED_LONG == var->mbv_type) {
 761             unsigned long *castme = (unsigned long*) var->mbv_storage;
 762             *castme = (unsigned long) int_value;
 763         } else if (PMIX_MCA_BASE_VAR_TYPE_UNSIGNED_LONG_LONG == var->mbv_type) {
 764             unsigned long long *castme = (unsigned long long*) var->mbv_storage;
 765             *castme = (unsigned long long) int_value;
 766         } else if (PMIX_MCA_BASE_VAR_TYPE_SIZE_T == var->mbv_type) {
 767             size_t *castme = (size_t*) var->mbv_storage;
 768             *castme = (size_t) int_value;
 769         } else if (PMIX_MCA_BASE_VAR_TYPE_BOOL == var->mbv_type) {
 770             bool *castme = (bool*) var->mbv_storage;
 771             *castme = !!int_value;
 772         }
 773 
 774         return ret;
 775     case PMIX_MCA_BASE_VAR_TYPE_DOUBLE:
 776         dst->lfval = strtod (src, NULL);
 777         break;
 778     case PMIX_MCA_BASE_VAR_TYPE_STRING:
 779     case PMIX_MCA_BASE_VAR_TYPE_VERSION_STRING:
 780         var_set_string (var, src);
 781         break;
 782     case PMIX_MCA_BASE_VAR_TYPE_MAX:
 783         return PMIX_ERROR;
 784     }
 785 
 786     return PMIX_SUCCESS;
 787 }
 788 
 789 /*
 790  * Set a variable
 791  */
 792 int pmix_mca_base_var_set_value (int vari, const void *value, size_t size, pmix_mca_base_var_source_t source,
 793                             const char *source_file)
 794 {
 795     pmix_mca_base_var_t *var;
 796     int ret;
 797 
 798     ret = var_get (vari, &var, true);
 799     if (PMIX_SUCCESS != ret) {
 800         return ret;
 801     }
 802 
 803     if (!PMIX_VAR_IS_VALID(var[0])) {
 804         return PMIX_ERR_BAD_PARAM;
 805     }
 806 
 807     if (!PMIX_VAR_IS_SETTABLE(var[0])) {
 808         return PMIX_ERR_PERM;
 809     }
 810 
 811     if (NULL != var->mbv_enumerator) {
 812         /* Validate */
 813         ret = var->mbv_enumerator->string_from_value(var->mbv_enumerator,
 814                                                      ((int *) value)[0], NULL);
 815         if (PMIX_SUCCESS != ret) {
 816             return ret;
 817         }
 818     }
 819 
 820     if (PMIX_MCA_BASE_VAR_TYPE_STRING != var->mbv_type && PMIX_MCA_BASE_VAR_TYPE_VERSION_STRING != var->mbv_type) {
 821         memmove (var->mbv_storage, value, pmix_var_type_sizes[var->mbv_type]);
 822     } else {
 823         var_set_string (var, (char *) value);
 824     }
 825 
 826     var->mbv_source = source;
 827 
 828     if (PMIX_MCA_BASE_VAR_SOURCE_FILE == source && NULL != source_file) {
 829         var->mbv_file_value = NULL;
 830         var->mbv_source_file = append_filename_to_list(source_file);
 831     }
 832 
 833     return PMIX_SUCCESS;
 834 }
 835 
 836 /*
 837  * Deregister a parameter
 838  */
 839 int pmix_mca_base_var_deregister(int vari)
 840 {
 841     pmix_mca_base_var_t *var;
 842     int ret;
 843 
 844     ret = var_get (vari, &var, false);
 845     if (PMIX_SUCCESS != ret) {
 846         return ret;
 847     }
 848 
 849     if (!PMIX_VAR_IS_VALID(var[0])) {
 850         return PMIX_ERR_BAD_PARAM;
 851     }
 852 
 853     /* Mark this parameter as invalid but keep its info in case this
 854        parameter is reregistered later */
 855     var->mbv_flags &= ~PMIX_MCA_BASE_VAR_FLAG_VALID;
 856 
 857     /* Done deregistering synonym */
 858     if (PMIX_MCA_BASE_VAR_FLAG_SYNONYM & var->mbv_flags) {
 859         return PMIX_SUCCESS;
 860     }
 861 
 862     /* Release the current value if it is a string. */
 863     if ((PMIX_MCA_BASE_VAR_TYPE_STRING == var->mbv_type || PMIX_MCA_BASE_VAR_TYPE_VERSION_STRING == var->mbv_type) &&
 864         var->mbv_storage->stringval) {
 865         free (var->mbv_storage->stringval);
 866         var->mbv_storage->stringval = NULL;
 867     } else if (var->mbv_enumerator && !var->mbv_enumerator->enum_is_static) {
 868         PMIX_RELEASE(var->mbv_enumerator);
 869     }
 870 
 871     var->mbv_enumerator = NULL;
 872 
 873     var->mbv_storage = NULL;
 874 
 875     return PMIX_SUCCESS;
 876 }
 877 
 878 static int var_get (int vari, pmix_mca_base_var_t **var_out, bool original)
 879 {
 880     pmix_mca_base_var_t *var;
 881 
 882     if (var_out) {
 883         *var_out = NULL;
 884     }
 885 
 886     /* Check for bozo cases */
 887     if (!pmix_mca_base_var_initialized) {
 888         return PMIX_ERROR;
 889     }
 890 
 891     if (vari < 0) {
 892         return PMIX_ERR_BAD_PARAM;
 893     }
 894 
 895     var = pmix_pointer_array_get_item (&pmix_mca_base_vars, vari);
 896     if (NULL == var) {
 897         return PMIX_ERR_BAD_PARAM;
 898     }
 899 
 900     if (PMIX_VAR_IS_SYNONYM(var[0]) && original) {
 901         return var_get(var->mbv_synonym_for, var_out, false);
 902     }
 903 
 904     if (var_out) {
 905         *var_out = var;
 906     }
 907 
 908     return PMIX_SUCCESS;
 909 }
 910 
 911 int pmix_mca_base_var_env_name(const char *param_name,
 912                           char **env_name)
 913 {
 914     int ret;
 915 
 916     assert (NULL != env_name);
 917 
 918     ret = asprintf(env_name, "%s%s", mca_prefix, param_name);
 919     if (0 > ret) {
 920         return PMIX_ERR_OUT_OF_RESOURCE;
 921     }
 922 
 923     return PMIX_SUCCESS;
 924 }
 925 
 926 /*
 927  * Find the index for an MCA parameter based on its names.
 928  */
 929 static int var_find_by_name (const char *full_name, int *vari, bool invalidok)
 930 {
 931     pmix_mca_base_var_t *var = NULL;
 932     void *tmp;
 933     int rc;
 934 
 935     rc = pmix_hash_table_get_value_ptr (&pmix_mca_base_var_index_hash, full_name, strlen (full_name),
 936                                         &tmp);
 937     if (PMIX_SUCCESS != rc) {
 938         return rc;
 939     }
 940 
 941     (void) var_get ((int)(uintptr_t) tmp, &var, false);
 942 
 943     if (invalidok || (var && PMIX_VAR_IS_VALID(var[0]))) {
 944         *vari = (int)(uintptr_t) tmp;
 945         return PMIX_SUCCESS;
 946     }
 947 
 948     return PMIX_ERR_NOT_FOUND;
 949 }
 950 
 951 static int var_find (const char *project_name, const char *framework_name,
 952                      const char *component_name, const char *variable_name,
 953                      bool invalidok)
 954 {
 955     char *full_name;
 956     int ret, vari;
 957 
 958     ret = pmix_mca_base_var_generate_full_name4 (NULL, framework_name, component_name,
 959                                             variable_name, &full_name);
 960     if (PMIX_SUCCESS != ret) {
 961         return PMIX_ERROR;
 962     }
 963 
 964     ret = var_find_by_name(full_name, &vari, invalidok);
 965 
 966     /* NTH: should we verify the name components match? */
 967 
 968     free (full_name);
 969 
 970     if (PMIX_SUCCESS != ret) {
 971         return ret;
 972     }
 973 
 974     return vari;
 975 }
 976 
 977 /*
 978  * Find the index for an MCA parameter based on its name components.
 979  */
 980 int pmix_mca_base_var_find (const char *project_name, const char *framework_name,
 981                        const char *component_name, const char *variable_name)
 982 {
 983     return var_find (project_name, framework_name, component_name, variable_name, false);
 984 }
 985 
 986 /*
 987  * Find the index for an MCA parameter based on full name.
 988  */
 989 int pmix_mca_base_var_find_by_name (const char *full_name, int *vari)
 990 {
 991     return var_find_by_name (full_name, vari, false);
 992 }
 993 
 994 int pmix_mca_base_var_set_flag (int vari, pmix_mca_base_var_flag_t flag, bool set)
 995 {
 996     pmix_mca_base_var_t *var;
 997     int ret;
 998 
 999     ret = var_get (vari, &var, true);
1000     if (PMIX_SUCCESS != ret || PMIX_VAR_IS_SYNONYM(var[0])) {
1001         return PMIX_ERR_BAD_PARAM;
1002     }
1003 
1004     var->mbv_flags = (var->mbv_flags & ~flag) | (set ? flag : 0);
1005 
1006     /* All done */
1007     return PMIX_SUCCESS;
1008 }
1009 
1010 /*
1011  * Return info on a parameter at an index
1012  */
1013 int pmix_mca_base_var_get (int vari, const pmix_mca_base_var_t **var)
1014 {
1015     int ret;
1016     ret = var_get (vari, (pmix_mca_base_var_t **) var, false);
1017 
1018     if (PMIX_SUCCESS != ret) {
1019         return ret;
1020     }
1021 
1022     if (!PMIX_VAR_IS_VALID(*(var[0]))) {
1023         return PMIX_ERR_NOT_FOUND;
1024     }
1025 
1026     return PMIX_SUCCESS;
1027 }
1028 
1029 /*
1030  * Make an argv-style list of strings suitable for an environment
1031  */
1032 int pmix_mca_base_var_build_env(char ***env, int *num_env, bool internal)
1033 {
1034     pmix_mca_base_var_t *var;
1035     size_t i, len;
1036     int ret=0;
1037 
1038     /* Check for bozo cases */
1039 
1040     if (!pmix_mca_base_var_initialized) {
1041         return PMIX_ERROR;
1042     }
1043 
1044     /* Iterate through all the registered parameters */
1045 
1046     len = pmix_pointer_array_get_size(&pmix_mca_base_vars);
1047     for (i = 0; i < len; ++i) {
1048         char *value_string;
1049         char *str = NULL;
1050 
1051         var = pmix_pointer_array_get_item (&pmix_mca_base_vars, i);
1052         if (NULL == var) {
1053             continue;
1054         }
1055 
1056         /* Don't output default values or internal variables (unless
1057            requested) */
1058         if (PMIX_MCA_BASE_VAR_SOURCE_DEFAULT == var->mbv_source ||
1059             (!internal && PMIX_VAR_IS_INTERNAL(var[0]))) {
1060             continue;
1061         }
1062 
1063         if ((PMIX_MCA_BASE_VAR_TYPE_STRING == var->mbv_type || PMIX_MCA_BASE_VAR_TYPE_VERSION_STRING == var->mbv_type) &&
1064             NULL == var->mbv_storage->stringval) {
1065             continue;
1066         }
1067 
1068         ret = var_value_string (var, &value_string);
1069         if (PMIX_SUCCESS != ret) {
1070             goto cleanup;
1071         }
1072 
1073         ret = asprintf (&str, "%s%s=%s", mca_prefix, var->mbv_full_name,
1074                         value_string);
1075         free (value_string);
1076         if (0 > ret) {
1077             goto cleanup;
1078         }
1079 
1080         pmix_argv_append(num_env, env, str);
1081         free(str);
1082 
1083         ret = PMIX_SUCCESS;
1084         switch (var->mbv_source) {
1085         case PMIX_MCA_BASE_VAR_SOURCE_FILE:
1086         case PMIX_MCA_BASE_VAR_SOURCE_OVERRIDE:
1087             ret = asprintf (&str, "%sSOURCE_%s=FILE:%s", mca_prefix, var->mbv_full_name,
1088                             pmix_mca_base_var_source_file (var));
1089             break;
1090         case PMIX_MCA_BASE_VAR_SOURCE_COMMAND_LINE:
1091             ret = asprintf (&str, "%sSOURCE_%s=COMMAND_LINE", mca_prefix, var->mbv_full_name);
1092             break;
1093         case PMIX_MCA_BASE_VAR_SOURCE_ENV:
1094         case PMIX_MCA_BASE_VAR_SOURCE_SET:
1095         case PMIX_MCA_BASE_VAR_SOURCE_DEFAULT:
1096             str = NULL;
1097             break;
1098         case PMIX_MCA_BASE_VAR_SOURCE_MAX:
1099             goto cleanup;
1100         }
1101 
1102         if (NULL != str) {
1103             pmix_argv_append(num_env, env, str);
1104             free(str);
1105         }
1106     }
1107     if (ret < 0) {
1108         ret = PMIX_ERR_OUT_OF_RESOURCE;
1109     }
1110 
1111     /* All done */
1112     return ret;
1113 
1114     /* Error condition */
1115 
1116  cleanup:
1117     if (*num_env > 0) {
1118         pmix_argv_free(*env);
1119         *num_env = 0;
1120         *env = NULL;
1121     }
1122     return PMIX_ERR_NOT_FOUND;
1123 }
1124 
1125 /*
1126  * Shut down the MCA parameter system (normally only invoked by the
1127  * MCA framework itself).
1128  */
1129 int pmix_mca_base_var_finalize(void)
1130 {
1131     pmix_object_t *pmixect;
1132     pmix_list_item_t *item;
1133     int size, i;
1134 
1135     if (pmix_mca_base_var_initialized) {
1136         size = pmix_pointer_array_get_size(&pmix_mca_base_vars);
1137         for (i = 0 ; i < size ; ++i) {
1138             pmixect = pmix_pointer_array_get_item (&pmix_mca_base_vars, i);
1139             if (NULL != pmixect) {
1140                 PMIX_RELEASE(pmixect);
1141             }
1142         }
1143         PMIX_DESTRUCT(&pmix_mca_base_vars);
1144 
1145         while (NULL !=
1146                (item = pmix_list_remove_first(&pmix_mca_base_var_file_values))) {
1147             PMIX_RELEASE(item);
1148         }
1149         PMIX_DESTRUCT(&pmix_mca_base_var_file_values);
1150 
1151         while (NULL !=
1152                (item = pmix_list_remove_first(&pmix_mca_base_envar_file_values))) {
1153             PMIX_RELEASE(item);
1154         }
1155         PMIX_DESTRUCT(&pmix_mca_base_envar_file_values);
1156 
1157         while (NULL !=
1158                (item = pmix_list_remove_first(&pmix_mca_base_var_override_values))) {
1159             PMIX_RELEASE(item);
1160         }
1161         PMIX_DESTRUCT(&pmix_mca_base_var_override_values);
1162 
1163         if( NULL != cwd ) {
1164             free(cwd);
1165             cwd = NULL;
1166         }
1167 
1168         pmix_mca_base_var_initialized = false;
1169         pmix_mca_base_var_count = 0;
1170 
1171         if (NULL != pmix_mca_base_var_file_list) {
1172             pmix_argv_free(pmix_mca_base_var_file_list);
1173         }
1174         pmix_mca_base_var_file_list = NULL;
1175 
1176         (void) pmix_mca_base_var_group_finalize ();
1177 
1178         PMIX_DESTRUCT(&pmix_mca_base_var_index_hash);
1179 
1180         free (pmix_mca_base_envar_files);
1181         pmix_mca_base_envar_files = NULL;
1182     }
1183 
1184     /* All done */
1185 
1186     return PMIX_SUCCESS;
1187 }
1188 
1189 
1190 /*************************************************************************/
1191 static int fixup_files(char **file_list, char * path, bool rel_path_search, char sep) {
1192     int exit_status = PMIX_SUCCESS;
1193     char **files = NULL;
1194     char **search_path = NULL;
1195     char * tmp_file = NULL;
1196     char **argv = NULL;
1197     char *rel_path;
1198     int mode = R_OK; /* The file exists, and we can read it */
1199     int count, i, argc = 0;
1200 
1201     search_path = pmix_argv_split(path, PMIX_ENV_SEP);
1202     files = pmix_argv_split(*file_list, sep);
1203     count = pmix_argv_count(files);
1204 
1205     rel_path = force_agg_path ? force_agg_path : cwd;
1206 
1207     /* Read in reverse order, so we can preserve the original ordering */
1208     for (i = 0 ; i < count; ++i) {
1209         char *msg_path = path;
1210         if (pmix_path_is_absolute(files[i])) {
1211             /* Absolute paths preserved */
1212             tmp_file = pmix_path_access(files[i], NULL, mode);
1213         } else if (!rel_path_search && NULL != strchr(files[i], PMIX_PATH_SEP[0])) {
1214             /* Resolve all relative paths:
1215              *  - If filename contains a "/" (e.g., "./foo" or "foo/bar")
1216              *    - look for it relative to cwd
1217              *    - if exists, use it
1218              *    - ow warn/error
1219              */
1220             msg_path = rel_path;
1221             tmp_file = pmix_path_access(files[i], rel_path, mode);
1222         } else {
1223             /* Resolve all relative paths:
1224              * - Use path resolution
1225              *    - if found and readable, use it
1226              *    - otherwise, warn/error
1227              */
1228             tmp_file = pmix_path_find (files[i], search_path, mode, NULL);
1229         }
1230 
1231         if (NULL == tmp_file) {
1232             pmix_show_help("help-pmix-mca-var.txt", "missing-param-file",
1233                            true, getpid(), files[i], msg_path);
1234             exit_status = PMIX_ERROR;
1235             break;
1236         }
1237 
1238         pmix_argv_append(&argc, &argv, tmp_file);
1239 
1240         free(tmp_file);
1241         tmp_file = NULL;
1242     }
1243 
1244     if (PMIX_SUCCESS == exit_status) {
1245         free(*file_list);
1246         *file_list = pmix_argv_join(argv, sep);
1247     }
1248 
1249     if( NULL != files ) {
1250         pmix_argv_free(files);
1251         files = NULL;
1252     }
1253 
1254     if( NULL != argv ) {
1255         pmix_argv_free(argv);
1256         argv = NULL;
1257     }
1258 
1259     if( NULL != search_path ) {
1260         pmix_argv_free(search_path);
1261         search_path = NULL;
1262     }
1263 
1264     return exit_status;
1265 }
1266 
1267 static int read_files(char *file_list, pmix_list_t *file_values, char sep)
1268 {
1269     char **tmp = pmix_argv_split(file_list, sep);
1270     int i, count;
1271 
1272     if (!tmp) {
1273         return PMIX_ERR_OUT_OF_RESOURCE;
1274     }
1275 
1276     count = pmix_argv_count(tmp);
1277 
1278     /* Iterate through all the files passed in -- read them in reverse
1279        order so that we preserve unix/shell path-like semantics (i.e.,
1280        the entries farthest to the left get precedence) */
1281 
1282     for (i = count - 1; i >= 0; --i) {
1283         char *file_name = append_filename_to_list (tmp[i]);
1284         pmix_mca_base_parse_paramfile(file_name, file_values);
1285     }
1286 
1287     pmix_argv_free (tmp);
1288 
1289     pmix_mca_base_internal_env_store();
1290 
1291     return PMIX_SUCCESS;
1292 }
1293 
1294 /******************************************************************************/
1295 static int register_variable (const char *project_name, const char *framework_name,
1296                               const char *component_name, const char *variable_name,
1297                               const char *description, pmix_mca_base_var_type_t type,
1298                               pmix_mca_base_var_enum_t *enumerator, int bind,
1299                               pmix_mca_base_var_flag_t flags, pmix_mca_base_var_info_lvl_t info_lvl,
1300                               pmix_mca_base_var_scope_t scope, int synonym_for,
1301                               void *storage)
1302 {
1303     int ret, var_index, group_index, tmp;
1304     pmix_mca_base_var_group_t *group;
1305     pmix_mca_base_var_t *var, *original = NULL;
1306 
1307     /* Developer error. Storage can not be NULL and type must exist */
1308     assert (((flags & PMIX_MCA_BASE_VAR_FLAG_SYNONYM) || NULL != storage) && type >= 0 && type < PMIX_MCA_BASE_VAR_TYPE_MAX);
1309 
1310 #if PMIX_ENABLE_DEBUG
1311     /* Developer error: check for alignments */
1312     uintptr_t align = 0;
1313     switch (type) {
1314     case PMIX_MCA_BASE_VAR_TYPE_INT:
1315         align = PMIX_ALIGNMENT_INT;
1316         break;
1317     case PMIX_MCA_BASE_VAR_TYPE_UNSIGNED_INT:
1318         align = PMIX_ALIGNMENT_INT;
1319         break;
1320     case PMIX_MCA_BASE_VAR_TYPE_UNSIGNED_LONG:
1321         align = PMIX_ALIGNMENT_LONG;
1322         break;
1323     case PMIX_MCA_BASE_VAR_TYPE_UNSIGNED_LONG_LONG:
1324         align = PMIX_ALIGNMENT_LONG_LONG;
1325         break;
1326     case PMIX_MCA_BASE_VAR_TYPE_SIZE_T:
1327         align = PMIX_ALIGNMENT_SIZE_T;
1328         break;
1329     case PMIX_MCA_BASE_VAR_TYPE_BOOL:
1330         align = PMIX_ALIGNMENT_BOOL;
1331         break;
1332     case PMIX_MCA_BASE_VAR_TYPE_DOUBLE:
1333         align = PMIX_ALIGNMENT_DOUBLE;
1334         break;
1335     case PMIX_MCA_BASE_VAR_TYPE_VERSION_STRING:
1336     case PMIX_MCA_BASE_VAR_TYPE_STRING:
1337     default:
1338         align = 0;
1339         break;
1340     }
1341 
1342     if (0 != align) {
1343         assert(((uintptr_t) storage) % align == 0);
1344     }
1345 
1346     /* Also check to ensure that synonym_for>=0 when
1347        MCA_BCASE_VAR_FLAG_SYNONYM is specified */
1348     if (flags & PMIX_MCA_BASE_VAR_FLAG_SYNONYM && synonym_for < 0) {
1349         assert((flags & PMIX_MCA_BASE_VAR_FLAG_SYNONYM) && synonym_for >= 0);
1350     }
1351 #endif
1352 
1353     if (flags & PMIX_MCA_BASE_VAR_FLAG_SYNONYM) {
1354         if (synonym_for < 0) {
1355             return PMIX_ERR_BAD_PARAM;
1356         }
1357         original = pmix_pointer_array_get_item (&pmix_mca_base_vars, synonym_for);
1358         if (NULL == original) {
1359             /* Attempting to create a synonym for a non-existent variable. probably a
1360              * developer error. */
1361             assert (NULL != original);
1362             return PMIX_ERR_NOT_FOUND;
1363         }
1364     }
1365 
1366     /* Initialize the array if it has never been initialized */
1367     if (!pmix_mca_base_var_initialized) {
1368         ret = pmix_mca_base_var_init();
1369         if (PMIX_SUCCESS != ret) {
1370             return ret;
1371         }
1372     }
1373 
1374     /* See if this entry is already in the array */
1375     var_index = var_find (project_name, framework_name, component_name, variable_name,
1376                           true);
1377 
1378     if (0 > var_index) {
1379         /* Create a new parameter entry */
1380         group_index = pmix_mca_base_var_group_register (project_name, framework_name, component_name,
1381                                                    NULL);
1382         if (-1 > group_index) {
1383             return group_index;
1384         }
1385 
1386         /* Read-only and constant variables can't be settable */
1387         if (scope < PMIX_MCA_BASE_VAR_SCOPE_LOCAL || (flags & PMIX_MCA_BASE_VAR_FLAG_DEFAULT_ONLY)) {
1388             if ((flags & PMIX_MCA_BASE_VAR_FLAG_DEFAULT_ONLY) && (flags & PMIX_MCA_BASE_VAR_FLAG_SETTABLE)) {
1389                 pmix_show_help("help-pmix-mca-var.txt", "invalid-flag-combination",
1390                                true, "PMIX_MCA_BASE_VAR_FLAG_DEFAULT_ONLY", "PMIX_MCA_BASE_VAR_FLAG_SETTABLE");
1391                 return PMIX_ERROR;
1392             }
1393 
1394             /* Should we print a warning for other cases? */
1395             flags &= ~PMIX_MCA_BASE_VAR_FLAG_SETTABLE;
1396         }
1397 
1398         var = PMIX_NEW(pmix_mca_base_var_t);
1399 
1400         var->mbv_type        = type;
1401         var->mbv_flags       = flags;
1402         var->mbv_group_index = group_index;
1403         var->mbv_info_lvl  = info_lvl;
1404         var->mbv_scope       = scope;
1405         var->mbv_synonym_for = synonym_for;
1406         var->mbv_bind        = bind;
1407 
1408         if (NULL != description) {
1409             var->mbv_description = strdup(description);
1410         }
1411 
1412         if (NULL != variable_name) {
1413             var->mbv_variable_name = strdup(variable_name);
1414             if (NULL == var->mbv_variable_name) {
1415                 PMIX_RELEASE(var);
1416                 return PMIX_ERR_OUT_OF_RESOURCE;
1417             }
1418         }
1419 
1420         ret = pmix_mca_base_var_generate_full_name4 (NULL, framework_name, component_name,
1421                                                 variable_name, &var->mbv_full_name);
1422         if (PMIX_SUCCESS != ret) {
1423             PMIX_RELEASE(var);
1424             return PMIX_ERROR;
1425         }
1426 
1427         ret = pmix_mca_base_var_generate_full_name4 (project_name, framework_name, component_name,
1428                                                 variable_name, &var->mbv_long_name);
1429         if (PMIX_SUCCESS != ret) {
1430             PMIX_RELEASE(var);
1431             return PMIX_ERROR;
1432         }
1433 
1434         /* Add it to the array.  Note that we copy the mca_var_t by value,
1435            so the entire contents of the struct is copied.  The synonym list
1436            will always be empty at this point, so there's no need for an
1437            extra RETAIN or RELEASE. */
1438         var_index = pmix_pointer_array_add (&pmix_mca_base_vars, var);
1439         if (0 > var_index) {
1440             PMIX_RELEASE(var);
1441             return PMIX_ERROR;
1442         }
1443 
1444         var->mbv_index = var_index;
1445 
1446         if (0 <= group_index) {
1447             pmix_mca_base_var_group_add_var (group_index, var_index);
1448         }
1449 
1450         pmix_mca_base_var_count++;
1451         if (0 <= var_find_by_name (var->mbv_full_name, &tmp, 0)) {
1452             /* XXX --- FIXME: variable overshadows an existing variable. this is difficult to support */
1453             assert (0);
1454         }
1455 
1456         pmix_hash_table_set_value_ptr (&pmix_mca_base_var_index_hash, var->mbv_full_name, strlen (var->mbv_full_name),
1457                                        (void *)(uintptr_t) var_index);
1458     } else {
1459         ret = var_get (var_index, &var, false);
1460         if (PMIX_SUCCESS != ret) {
1461             /* Shouldn't ever happen */
1462             return PMIX_ERROR;
1463         }
1464 
1465         ret = pmix_mca_base_var_group_get_internal (var->mbv_group_index, &group, true);
1466         if (PMIX_SUCCESS != ret) {
1467             /* Shouldn't ever happen */
1468             return PMIX_ERROR;
1469         }
1470 
1471         if (!group->group_isvalid) {
1472             group->group_isvalid = true;
1473         }
1474 
1475         /* Verify the name components match */
1476         if (0 != compare_strings(framework_name, group->group_framework) ||
1477             0 != compare_strings(component_name, group->group_component) ||
1478             0 != compare_strings(variable_name, var->mbv_variable_name)) {
1479             pmix_show_help("help-pmix-mca-var.txt", "var-name-conflict",
1480                            true, var->mbv_full_name, framework_name,
1481                            component_name, variable_name,
1482                            group->group_framework, group->group_component,
1483                            var->mbv_variable_name);
1484             /* This is developer error. abort! */
1485             assert (0);
1486             return PMIX_ERROR;
1487         }
1488 
1489         if (var->mbv_type != type) {
1490 #if PMIX_ENABLE_DEBUG
1491             pmix_show_help("help-pmix-mca-var.txt",
1492                            "re-register-with-different-type",
1493                            true, var->mbv_full_name);
1494 #endif
1495             return PMIX_ERR_VALUE_OUT_OF_BOUNDS;
1496         }
1497     }
1498 
1499     if (PMIX_MCA_BASE_VAR_TYPE_BOOL == var->mbv_type) {
1500         enumerator = &pmix_mca_base_var_enum_bool;
1501     } else if (NULL != enumerator) {
1502         if (var->mbv_enumerator) {
1503             PMIX_RELEASE (var->mbv_enumerator);
1504         }
1505 
1506         if (!enumerator->enum_is_static) {
1507             PMIX_RETAIN(enumerator);
1508         }
1509     }
1510 
1511     var->mbv_enumerator = enumerator;
1512 
1513     if (!original) {
1514         var->mbv_storage = storage;
1515 
1516         /* make a copy of the default string value */
1517         if ((PMIX_MCA_BASE_VAR_TYPE_STRING == type || PMIX_MCA_BASE_VAR_TYPE_VERSION_STRING == type) && NULL != ((char **)storage)[0]) {
1518             ((char **)storage)[0] = strdup (((char **)storage)[0]);
1519         }
1520     } else {
1521         /* synonym variable */
1522         pmix_value_array_append_item(&original->mbv_synonyms, &var_index);
1523     }
1524 
1525     /* go ahead and mark this variable as valid */
1526     var->mbv_flags |= PMIX_MCA_BASE_VAR_FLAG_VALID;
1527 
1528     ret = var_set_initial (var, original);
1529     if (PMIX_SUCCESS != ret) {
1530         return ret;
1531     }
1532 
1533     /* All done */
1534     return var_index;
1535 }
1536 
1537 int pmix_mca_base_var_register (const char *project_name, const char *framework_name,
1538                            const char *component_name, const char *variable_name,
1539                            const char *description, pmix_mca_base_var_type_t type,
1540                            pmix_mca_base_var_enum_t *enumerator, int bind,
1541                            pmix_mca_base_var_flag_t flags,
1542                            pmix_mca_base_var_info_lvl_t info_lvl,
1543                            pmix_mca_base_var_scope_t scope, void *storage)
1544 {
1545     /* Only integer variables can have enumerator */
1546     assert (NULL == enumerator || (PMIX_MCA_BASE_VAR_TYPE_INT == type || PMIX_MCA_BASE_VAR_TYPE_UNSIGNED_INT == type));
1547 
1548     return register_variable (project_name, framework_name, component_name,
1549                               variable_name, description, type, enumerator,
1550                               bind, flags, info_lvl, scope, -1, storage);
1551 }
1552 
1553 int pmix_mca_base_component_var_register (const pmix_mca_base_component_t *component,
1554                                           const char *variable_name, const char *description,
1555                                           pmix_mca_base_var_type_t type, pmix_mca_base_var_enum_t *enumerator,
1556                                           int bind, pmix_mca_base_var_flag_t flags,
1557                                           pmix_mca_base_var_info_lvl_t info_lvl,
1558                                           pmix_mca_base_var_scope_t scope, void *storage)
1559 {
1560     return pmix_mca_base_var_register (component->pmix_mca_project_name,
1561                                        component->pmix_mca_type_name,
1562                                        component->pmix_mca_component_name,
1563                                        variable_name, description, type, enumerator,
1564                                        bind, flags | PMIX_MCA_BASE_VAR_FLAG_DWG,
1565                                        info_lvl, scope, storage);
1566 }
1567 
1568 int pmix_mca_base_framework_var_register (const pmix_mca_base_framework_t *framework,
1569                                           const char *variable_name,
1570                                           const char *help_msg, pmix_mca_base_var_type_t type,
1571                                           pmix_mca_base_var_enum_t *enumerator, int bind,
1572                                           pmix_mca_base_var_flag_t flags,
1573                                           pmix_mca_base_var_info_lvl_t info_level,
1574                                           pmix_mca_base_var_scope_t scope, void *storage)
1575 {
1576     return pmix_mca_base_var_register (framework->framework_project, framework->framework_name,
1577                                        "base", variable_name, help_msg, type, enumerator, bind,
1578                                        flags | PMIX_MCA_BASE_VAR_FLAG_DWG, info_level, scope, storage);
1579 }
1580 
1581 int pmix_mca_base_var_register_synonym (int synonym_for, const char *project_name,
1582                                         const char *framework_name,
1583                                         const char *component_name,
1584                                         const char *synonym_name,
1585                                         pmix_mca_base_var_syn_flag_t flags)
1586 {
1587     pmix_mca_base_var_flag_t var_flags = (pmix_mca_base_var_flag_t) PMIX_MCA_BASE_VAR_FLAG_SYNONYM;
1588     pmix_mca_base_var_t *var;
1589     int ret;
1590 
1591     ret = var_get (synonym_for, &var, false);
1592     if (PMIX_SUCCESS != ret || PMIX_VAR_IS_SYNONYM(var[0])) {
1593         return PMIX_ERR_BAD_PARAM;
1594     }
1595 
1596     if (flags & PMIX_MCA_BASE_VAR_SYN_FLAG_DEPRECATED) {
1597         var_flags |= PMIX_MCA_BASE_VAR_FLAG_DEPRECATED;
1598     }
1599     if (flags & PMIX_MCA_BASE_VAR_SYN_FLAG_INTERNAL) {
1600         var_flags |= PMIX_MCA_BASE_VAR_FLAG_INTERNAL;
1601     }
1602 
1603     return register_variable (project_name, framework_name, component_name,
1604                               synonym_name, var->mbv_description, var->mbv_type, var->mbv_enumerator,
1605                               var->mbv_bind, var_flags, var->mbv_info_lvl, var->mbv_scope,
1606                               synonym_for, NULL);
1607 }
1608 
1609 static int var_get_env (pmix_mca_base_var_t *var, const char *name, char **source, char **value)
1610 {
1611     char *source_env, *value_env;
1612     int ret;
1613 
1614     ret = asprintf (&source_env, "%sSOURCE_%s", mca_prefix, name);
1615     if (0 > ret) {
1616         return PMIX_ERROR;
1617     }
1618 
1619     ret = asprintf (&value_env, "%s%s", mca_prefix, name);
1620     if (0 > ret) {
1621         free (source_env);
1622         return PMIX_ERROR;
1623     }
1624 
1625     *source = getenv (source_env);
1626     *value = getenv (value_env);
1627 
1628     free (source_env);
1629     free (value_env);
1630 
1631     if (NULL == *value) {
1632         *source = NULL;
1633         return PMIX_ERR_NOT_FOUND;
1634     }
1635 
1636     return PMIX_SUCCESS;
1637 }
1638 
1639 /*
1640  * Lookup a param in the environment
1641  */
1642 static int var_set_from_env (pmix_mca_base_var_t *var, pmix_mca_base_var_t *original)
1643 {
1644     const char *var_full_name = var->mbv_full_name;
1645     const char *var_long_name = var->mbv_long_name;
1646     bool deprecated = PMIX_VAR_IS_DEPRECATED(var[0]);
1647     bool is_synonym = PMIX_VAR_IS_SYNONYM(var[0]);
1648     char *source_env, *value_env;
1649     int ret;
1650 
1651     ret = var_get_env (var, var_long_name, &source_env, &value_env);
1652     if (PMIX_SUCCESS != ret) {
1653         ret = var_get_env (var, var_full_name, &source_env, &value_env);
1654     }
1655 
1656     if (PMIX_SUCCESS != ret) {
1657         return ret;
1658     }
1659 
1660     /* we found an environment variable but this variable is default-only. print
1661        a warning. */
1662     if (PMIX_VAR_IS_DEFAULT_ONLY(original[0])) {
1663         pmix_show_help("help-pmix-mca-var.txt", "default-only-param-set",
1664                        true, var_full_name);
1665 
1666         return PMIX_ERR_NOT_FOUND;
1667     }
1668 
1669     if (PMIX_MCA_BASE_VAR_SOURCE_OVERRIDE == original->mbv_source) {
1670         if (!pmix_mca_base_var_suppress_override_warning) {
1671             pmix_show_help("help-pmix-mca-var.txt", "overridden-param-set",
1672                            true, var_full_name);
1673         }
1674 
1675         return PMIX_ERR_NOT_FOUND;
1676     }
1677 
1678     original->mbv_source = PMIX_MCA_BASE_VAR_SOURCE_ENV;
1679 
1680     if (NULL != source_env) {
1681         if (0 == strncasecmp (source_env, "file:", 5)) {
1682             original->mbv_source_file = append_filename_to_list(source_env + 5);
1683             if (0 == strcmp (var->mbv_source_file, pmix_mca_base_var_override_file)) {
1684                 original->mbv_source = PMIX_MCA_BASE_VAR_SOURCE_OVERRIDE;
1685             } else {
1686                 original->mbv_source = PMIX_MCA_BASE_VAR_SOURCE_FILE;
1687             }
1688         } else if (0 == strcasecmp (source_env, "command")) {
1689             var->mbv_source = PMIX_MCA_BASE_VAR_SOURCE_COMMAND_LINE;
1690         }
1691     }
1692 
1693     if (deprecated) {
1694         const char *new_variable = "None (going away)";
1695 
1696         if (is_synonym) {
1697             new_variable = var->mbv_full_name;
1698         }
1699 
1700         switch (var->mbv_source) {
1701         case PMIX_MCA_BASE_VAR_SOURCE_ENV:
1702             pmix_show_help("help-pmix-mca-var.txt", "deprecated-mca-env",
1703                            true, var_full_name, new_variable);
1704             break;
1705         case PMIX_MCA_BASE_VAR_SOURCE_COMMAND_LINE:
1706             pmix_show_help("help-pmix-mca-var.txt", "deprecated-mca-cli",
1707                            true, var_full_name, new_variable);
1708             break;
1709         case PMIX_MCA_BASE_VAR_SOURCE_FILE:
1710         case PMIX_MCA_BASE_VAR_SOURCE_OVERRIDE:
1711             pmix_show_help("help-pmix-mca-var.txt", "deprecated-mca-file",
1712                            true, var_full_name, pmix_mca_base_var_source_file (var),
1713                            new_variable);
1714             break;
1715 
1716         case PMIX_MCA_BASE_VAR_SOURCE_DEFAULT:
1717         case PMIX_MCA_BASE_VAR_SOURCE_MAX:
1718         case PMIX_MCA_BASE_VAR_SOURCE_SET:
1719             /* silence compiler warnings about unhandled enumerations */
1720             break;
1721         }
1722     }
1723 
1724     return var_set_from_string (original, value_env);
1725 }
1726 
1727 /*
1728  * Lookup a param in the files
1729  */
1730 static int var_set_from_file (pmix_mca_base_var_t *var, pmix_mca_base_var_t *original, pmix_list_t *file_values)
1731 {
1732     const char *var_full_name = var->mbv_full_name;
1733     const char *var_long_name = var->mbv_long_name;
1734     bool deprecated = PMIX_VAR_IS_DEPRECATED(var[0]);
1735     bool is_synonym = PMIX_VAR_IS_SYNONYM(var[0]);
1736     pmix_mca_base_var_file_value_t *fv;
1737 
1738     /* Scan through the list of values read in from files and try to
1739        find a match.  If we do, cache it on the param (for future
1740        lookups) and save it in the storage. */
1741 
1742     PMIX_LIST_FOREACH(fv, file_values, pmix_mca_base_var_file_value_t) {
1743         if (0 != strcmp(fv->mbvfv_var, var_full_name) &&
1744             0 != strcmp(fv->mbvfv_var, var_long_name)) {
1745             continue;
1746         }
1747 
1748         /* found it */
1749         if (PMIX_VAR_IS_DEFAULT_ONLY(var[0])) {
1750             pmix_show_help("help-pmix-mca-var.txt", "default-only-param-set",
1751                            true, var_full_name);
1752 
1753             return PMIX_ERR_NOT_FOUND;
1754         }
1755 
1756         if (PMIX_MCA_BASE_VAR_FLAG_ENVIRONMENT_ONLY & original->mbv_flags) {
1757             pmix_show_help("help-pmix-mca-var.txt", "environment-only-param",
1758                            true, var_full_name, fv->mbvfv_value,
1759                            fv->mbvfv_file);
1760 
1761             return PMIX_ERR_NOT_FOUND;
1762         }
1763 
1764         if (PMIX_MCA_BASE_VAR_SOURCE_OVERRIDE == original->mbv_source) {
1765             if (!pmix_mca_base_var_suppress_override_warning) {
1766                 pmix_show_help("help-pmix-mca-var.txt", "overridden-param-set",
1767                                true, var_full_name);
1768             }
1769 
1770             return PMIX_ERR_NOT_FOUND;
1771         }
1772 
1773         if (deprecated) {
1774             const char *new_variable = "None (going away)";
1775 
1776             if (is_synonym) {
1777                 new_variable = original->mbv_full_name;
1778             }
1779 
1780             pmix_show_help("help-pmix-mca-var.txt", "deprecated-mca-file",
1781                            true, var_full_name, fv->mbvfv_file,
1782                            new_variable);
1783         }
1784 
1785         original->mbv_file_value = (void *) fv;
1786         original->mbv_source = PMIX_MCA_BASE_VAR_SOURCE_FILE;
1787         if (is_synonym) {
1788             var->mbv_file_value = (void *) fv;
1789             var->mbv_source = PMIX_MCA_BASE_VAR_SOURCE_FILE;
1790         }
1791 
1792         return var_set_from_string (original, fv->mbvfv_value);
1793     }
1794 
1795     return PMIX_ERR_NOT_FOUND;
1796 }
1797 
1798 /*
1799  * Lookup the initial value for a parameter
1800  */
1801 static int var_set_initial (pmix_mca_base_var_t *var, pmix_mca_base_var_t *original)
1802 {
1803     int ret;
1804 
1805     if (original) {
1806         /* synonym */
1807         var->mbv_source = original->mbv_source;
1808         var->mbv_file_value = original->mbv_file_value;
1809         var->mbv_source_file = original->mbv_source_file;
1810     } else {
1811         var->mbv_source = PMIX_MCA_BASE_VAR_SOURCE_DEFAULT;
1812         original = var;
1813     }
1814 
1815     /* Check all the places that the param may be hiding, in priority
1816        order. If the default only flag is set the user will get a
1817        warning if they try to set a value from the environment or a
1818        file. */
1819     ret = var_set_from_file (var, original, &pmix_mca_base_var_override_values);
1820     if (PMIX_SUCCESS == ret) {
1821         var->mbv_flags = ~PMIX_MCA_BASE_VAR_FLAG_SETTABLE & (var->mbv_flags | PMIX_MCA_BASE_VAR_FLAG_OVERRIDE);
1822         var->mbv_source = PMIX_MCA_BASE_VAR_SOURCE_OVERRIDE;
1823     }
1824 
1825     ret = var_set_from_env (var, original);
1826     if (PMIX_ERR_NOT_FOUND != ret) {
1827         return ret;
1828     }
1829 
1830     ret = var_set_from_file (var, original, &pmix_mca_base_envar_file_values);
1831     if (PMIX_ERR_NOT_FOUND != ret) {
1832         return ret;
1833     }
1834 
1835     ret = var_set_from_file (var, original, &pmix_mca_base_var_file_values);
1836     if (PMIX_ERR_NOT_FOUND != ret) {
1837         return ret;
1838     }
1839 
1840     return PMIX_SUCCESS;
1841 }
1842 
1843 /*
1844  * Create an empty param container
1845  */
1846 static void var_constructor(pmix_mca_base_var_t *var)
1847 {
1848     memset ((char *) var + sizeof (var->super), 0, sizeof (*var) - sizeof (var->super));
1849 
1850     var->mbv_type = PMIX_MCA_BASE_VAR_TYPE_MAX;
1851     PMIX_CONSTRUCT(&var->mbv_synonyms, pmix_value_array_t);
1852     pmix_value_array_init (&var->mbv_synonyms, sizeof (int));
1853 }
1854 
1855 
1856 /*
1857  * Free all the contents of a param container
1858  */
1859 static void var_destructor(pmix_mca_base_var_t *var)
1860 {
1861     if ((PMIX_MCA_BASE_VAR_TYPE_STRING == var->mbv_type ||
1862                 PMIX_MCA_BASE_VAR_TYPE_VERSION_STRING == var->mbv_type) &&
1863         NULL != var->mbv_storage &&
1864         NULL != var->mbv_storage->stringval) {
1865         free (var->mbv_storage->stringval);
1866         var->mbv_storage->stringval = NULL;
1867     }
1868 
1869     /* don't release the boolean enumerator */
1870     if (var->mbv_enumerator && !var->mbv_enumerator->enum_is_static) {
1871         PMIX_RELEASE(var->mbv_enumerator);
1872     }
1873 
1874     if (NULL != var->mbv_variable_name) {
1875         free(var->mbv_variable_name);
1876     }
1877     if (NULL != var->mbv_full_name) {
1878         free(var->mbv_full_name);
1879     }
1880     if (NULL != var->mbv_long_name) {
1881         free(var->mbv_long_name);
1882     }
1883 
1884     if (NULL != var->mbv_description) {
1885         free(var->mbv_description);
1886     }
1887 
1888     /* Destroy the synonym array */
1889     PMIX_DESTRUCT(&var->mbv_synonyms);
1890 
1891     /* mark this parameter as invalid */
1892     var->mbv_type = PMIX_MCA_BASE_VAR_TYPE_MAX;
1893 
1894 #if PMIX_ENABLE_DEBUG
1895     /* Cheap trick to reset everything to NULL */
1896     memset ((char *) var + sizeof (var->super), 0, sizeof (*var) - sizeof (var->super));
1897 #endif
1898 }
1899 
1900 
1901 static void fv_constructor(pmix_mca_base_var_file_value_t *f)
1902 {
1903     memset ((char *) f + sizeof (f->super), 0, sizeof (*f) - sizeof (f->super));
1904 }
1905 
1906 
1907 static void fv_destructor(pmix_mca_base_var_file_value_t *f)
1908 {
1909     if (NULL != f->mbvfv_var) {
1910         free(f->mbvfv_var);
1911     }
1912     if (NULL != f->mbvfv_value) {
1913         free(f->mbvfv_value);
1914     }
1915     /* the file name is stored in mca_*/
1916     fv_constructor(f);
1917 }
1918 
1919 static char *source_name(pmix_mca_base_var_t *var)
1920 {
1921     char *ret;
1922 
1923     if (PMIX_MCA_BASE_VAR_SOURCE_FILE == var->mbv_source || PMIX_MCA_BASE_VAR_SOURCE_OVERRIDE == var->mbv_source) {
1924         struct pmix_mca_base_var_file_value_t *fv = var->mbv_file_value;
1925         int rc;
1926 
1927         if (fv) {
1928             rc = asprintf(&ret, "file (%s:%d)", fv->mbvfv_file, fv->mbvfv_lineno);
1929         } else {
1930             rc = asprintf(&ret, "file (%s)", var->mbv_source_file);
1931         }
1932 
1933         /* some compilers will warn if the return code of asprintf is not checked (even if it is cast to void) */
1934         if (0 > rc) {
1935             return NULL;
1936         }
1937         return ret;
1938     } else if (PMIX_MCA_BASE_VAR_SOURCE_MAX <= var->mbv_source) {
1939         return strdup ("unknown(!!)");
1940     }
1941 
1942     return strdup (pmix_var_source_names[var->mbv_source]);
1943 }
1944 
1945 static int var_value_string (pmix_mca_base_var_t *var, char **value_string)
1946 {
1947     pmix_mca_base_var_storage_t *value=NULL;
1948     int ret;
1949 
1950     assert (PMIX_MCA_BASE_VAR_TYPE_MAX > var->mbv_type);
1951 
1952     ret = pmix_mca_base_var_get_value(var->mbv_index, &value, NULL, NULL);
1953     if (PMIX_SUCCESS != ret || NULL == value) {
1954         return ret;
1955     }
1956 
1957     if (NULL == var->mbv_enumerator) {
1958         switch (var->mbv_type) {
1959         case PMIX_MCA_BASE_VAR_TYPE_INT:
1960             ret = asprintf (value_string, "%d", value->intval);
1961             break;
1962         case PMIX_MCA_BASE_VAR_TYPE_UNSIGNED_INT:
1963             ret = asprintf (value_string, "%u", value->uintval);
1964             break;
1965         case PMIX_MCA_BASE_VAR_TYPE_UNSIGNED_LONG:
1966             ret = asprintf (value_string, "%lu", value->ulval);
1967             break;
1968         case PMIX_MCA_BASE_VAR_TYPE_UNSIGNED_LONG_LONG:
1969             ret = asprintf (value_string, "%llu", value->ullval);
1970             break;
1971         case PMIX_MCA_BASE_VAR_TYPE_SIZE_T:
1972             ret = asprintf (value_string, "%" PRIsize_t, value->sizetval);
1973             break;
1974         case PMIX_MCA_BASE_VAR_TYPE_STRING:
1975         case PMIX_MCA_BASE_VAR_TYPE_VERSION_STRING:
1976             ret = asprintf (value_string, "%s",
1977                             value->stringval ? value->stringval : "");
1978             break;
1979         case PMIX_MCA_BASE_VAR_TYPE_BOOL:
1980             ret = asprintf (value_string, "%d", value->boolval);
1981             break;
1982         case PMIX_MCA_BASE_VAR_TYPE_DOUBLE:
1983             ret = asprintf (value_string, "%lf", value->lfval);
1984             break;
1985         default:
1986             ret = -1;
1987             break;
1988         }
1989 
1990         ret = (0 > ret) ? PMIX_ERR_OUT_OF_RESOURCE : PMIX_SUCCESS;
1991     } else {
1992         /* we use an enumerator to handle string->bool and bool->string conversion */
1993         if (PMIX_MCA_BASE_VAR_TYPE_BOOL == var->mbv_type) {
1994             ret = var->mbv_enumerator->string_from_value(var->mbv_enumerator, value->boolval, value_string);
1995         } else {
1996             ret = var->mbv_enumerator->string_from_value(var->mbv_enumerator, value->intval, value_string);
1997         }
1998 
1999         if (PMIX_SUCCESS != ret) {
2000             return ret;
2001         }
2002     }
2003 
2004     return ret;
2005 }
2006 
2007 int pmix_mca_base_var_check_exclusive (const char *project,
2008                                   const char *type_a,
2009                                   const char *component_a,
2010                                   const char *param_a,
2011                                   const char *type_b,
2012                                   const char *component_b,
2013                                   const char *param_b)
2014 {
2015     pmix_mca_base_var_t *var_a = NULL, *var_b = NULL;
2016     int var_ai, var_bi;
2017 
2018     /* XXX -- Remove me once the project name is in the componennt */
2019     project = NULL;
2020 
2021     var_ai = pmix_mca_base_var_find (project, type_a, component_a, param_a);
2022     var_bi = pmix_mca_base_var_find (project, type_b, component_b, param_b);
2023     if (var_bi < 0 || var_ai < 0) {
2024         return PMIX_ERR_NOT_FOUND;
2025     }
2026 
2027     (void) var_get (var_ai, &var_a, true);
2028     (void) var_get (var_bi, &var_b, true);
2029     if (NULL == var_a || NULL == var_b) {
2030         return PMIX_ERR_NOT_FOUND;
2031     }
2032 
2033     if (PMIX_MCA_BASE_VAR_SOURCE_DEFAULT != var_a->mbv_source &&
2034         PMIX_MCA_BASE_VAR_SOURCE_DEFAULT != var_b->mbv_source) {
2035         char *str_a, *str_b;
2036 
2037         /* Form cosmetic string names for A */
2038         str_a = source_name(var_a);
2039 
2040         /* Form cosmetic string names for B */
2041         str_b = source_name(var_b);
2042 
2043         /* Print it all out */
2044         pmix_show_help("help-pmix-mca-var.txt",
2045                        "mutually-exclusive-vars",
2046                        true, var_a->mbv_full_name,
2047                        str_a, var_b->mbv_full_name,
2048                        str_b);
2049 
2050         /* Free the temp strings */
2051         free(str_a);
2052         free(str_b);
2053 
2054         return PMIX_ERR_BAD_PARAM;
2055     }
2056 
2057     return PMIX_SUCCESS;
2058 }
2059 
2060 int pmix_mca_base_var_get_count (void)
2061 {
2062     return pmix_mca_base_var_count;
2063 }
2064 
2065 int pmix_mca_base_var_dump(int vari, char ***out, pmix_mca_base_var_dump_type_t output_type)
2066 {
2067     const char *framework, *component, *full_name;
2068     int i, line_count, line = 0, enum_count = 0;
2069     char *value_string, *source_string, *tmp;
2070     int synonym_count, ret, *synonyms = NULL;
2071     pmix_mca_base_var_t *var, *original=NULL;
2072     pmix_mca_base_var_group_t *group;
2073 
2074     ret = var_get(vari, &var, false);
2075     if (PMIX_SUCCESS != ret) {
2076         return ret;
2077     }
2078 
2079     ret = pmix_mca_base_var_group_get_internal(var->mbv_group_index, &group, false);
2080     if (PMIX_SUCCESS != ret) {
2081         return ret;
2082     }
2083 
2084     if (PMIX_VAR_IS_SYNONYM(var[0])) {
2085         ret = var_get(var->mbv_synonym_for, &original, false);
2086         if (PMIX_SUCCESS != ret) {
2087             return ret;
2088         }
2089         /* just for protection... */
2090         if (NULL == original) {
2091             return PMIX_ERR_NOT_FOUND;
2092         }
2093     }
2094 
2095     framework = group->group_framework;
2096     component = group->group_component ? group->group_component : "base";
2097     full_name = var->mbv_full_name;
2098 
2099     synonym_count = pmix_value_array_get_size(&var->mbv_synonyms);
2100     if (synonym_count) {
2101         synonyms = PMIX_VALUE_ARRAY_GET_BASE(&var->mbv_synonyms, int);
2102     }
2103 
2104     ret = var_value_string (var, &value_string);
2105     if (PMIX_SUCCESS != ret) {
2106         return ret;
2107     }
2108 
2109     source_string = source_name(var);
2110     if (NULL == source_string) {
2111         free (value_string);
2112         return PMIX_ERR_OUT_OF_RESOURCE;
2113     }
2114 
2115     if (PMIX_MCA_BASE_VAR_DUMP_PARSABLE == output_type) {
2116         if (NULL != var->mbv_enumerator) {
2117             (void) var->mbv_enumerator->get_count(var->mbv_enumerator, &enum_count);
2118         }
2119 
2120         line_count = 8 + (var->mbv_description ? 1 : 0) + (PMIX_VAR_IS_SYNONYM(var[0]) ? 1 : synonym_count) +
2121             enum_count;
2122 
2123         *out = (char **) calloc (line_count + 1, sizeof (char *));
2124         if (NULL == *out) {
2125             free (value_string);
2126             free (source_string);
2127             return PMIX_ERR_OUT_OF_RESOURCE;
2128         }
2129 
2130         /* build the message*/
2131         ret = asprintf(&tmp, "mca:%s:%s:param:%s:", framework, component, full_name);
2132         if (0 > ret) {
2133             return PMIX_ERR_OUT_OF_RESOURCE;
2134         }
2135 
2136         /* Output the value */
2137         char *colon = strchr(value_string, ':');
2138         if (NULL != colon) {
2139             ret = asprintf(out[0] + line++, "%svalue:\"%s\"", tmp, value_string);
2140         } else {
2141             ret = asprintf(out[0] + line++, "%svalue:%s", tmp, value_string);
2142         }
2143         if (0 > ret) {
2144             return PMIX_ERR_OUT_OF_RESOURCE;
2145         }
2146 
2147         /* Output the source */
2148         ret = asprintf(out[0] + line++, "%ssource:%s", tmp, source_string);
2149         if (0 > ret) {
2150             return PMIX_ERR_OUT_OF_RESOURCE;
2151         }
2152 
2153         /* Output whether it's read only or writable */
2154         ret = asprintf(out[0] + line++, "%sstatus:%s", tmp, PMIX_VAR_IS_DEFAULT_ONLY(var[0]) ? "read-only" : "writeable");
2155         if (0 > ret) {
2156             return PMIX_ERR_OUT_OF_RESOURCE;
2157         }
2158 
2159         /* Output the info level of this parametere */
2160         ret = asprintf(out[0] + line++, "%slevel:%d", tmp, var->mbv_info_lvl + 1);
2161         if (0 > ret) {
2162             return PMIX_ERR_OUT_OF_RESOURCE;
2163         }
2164 
2165         /* If it has a help message, output the help message */
2166         if (var->mbv_description) {
2167             ret = asprintf(out[0] + line++, "%shelp:%s", tmp, var->mbv_description);
2168         }
2169         if (0 > ret) {
2170             return PMIX_ERR_OUT_OF_RESOURCE;
2171         }
2172 
2173         if (NULL != var->mbv_enumerator) {
2174             for (i = 0 ; i < enum_count ; ++i) {
2175                 const char *enum_string = NULL;
2176                 int enum_value;
2177 
2178                 ret = var->mbv_enumerator->get_value(var->mbv_enumerator, i, &enum_value,
2179                                                      &enum_string);
2180                 if (PMIX_SUCCESS != ret) {
2181                     continue;
2182                 }
2183 
2184                 ret = asprintf(out[0] + line++, "%senumerator:value:%d:%s", tmp, enum_value, enum_string);
2185                 if (0 > ret) {
2186                     return PMIX_ERR_OUT_OF_RESOURCE;
2187                 }
2188             }
2189         }
2190 
2191         /* Is this variable deprecated? */
2192         ret = asprintf(out[0] + line++, "%sdeprecated:%s", tmp, PMIX_VAR_IS_DEPRECATED(var[0]) ? "yes" : "no");
2193         if (0 > ret) {
2194             return PMIX_ERR_OUT_OF_RESOURCE;
2195         }
2196 
2197         ret = asprintf(out[0] + line++, "%stype:%s", tmp, pmix_var_type_names[var->mbv_type]);
2198         if (0 > ret) {
2199             return PMIX_ERR_OUT_OF_RESOURCE;
2200         }
2201 
2202         /* Does this parameter have any synonyms or is it a synonym? */
2203         if (PMIX_VAR_IS_SYNONYM(var[0])) {
2204             ret = asprintf(out[0] + line++, "%ssynonym_of:name:%s", tmp, original->mbv_full_name);
2205             if (0 > ret) {
2206                 return PMIX_ERR_OUT_OF_RESOURCE;
2207             }
2208         } else if (pmix_value_array_get_size(&var->mbv_synonyms)) {
2209             for (i = 0 ; i < synonym_count ; ++i) {
2210                 pmix_mca_base_var_t *synonym;
2211 
2212                 ret = var_get(synonyms[i], &synonym, false);
2213                 if (PMIX_SUCCESS != ret) {
2214                     continue;
2215                 }
2216 
2217                 ret = asprintf(out[0] + line++, "%ssynonym:name:%s", tmp, synonym->mbv_full_name);
2218                 if (0 > ret) {
2219                     return PMIX_ERR_OUT_OF_RESOURCE;
2220                 }
2221             }
2222         }
2223 
2224         free (tmp);
2225     } else if (PMIX_MCA_BASE_VAR_DUMP_READABLE == output_type) {
2226         /* There will be at most three lines in the pretty print case */
2227         *out = (char **) calloc (4, sizeof (char *));
2228         if (NULL == *out) {
2229             free (value_string);
2230             free (source_string);
2231             return PMIX_ERR_OUT_OF_RESOURCE;
2232         }
2233 
2234         ret = asprintf (out[0], "%s \"%s\" (current value: \"%s\", data source: %s, level: %d %s, type: %s",
2235                         PMIX_VAR_IS_DEFAULT_ONLY(var[0]) ? "informational" : "parameter",
2236                         full_name, value_string, source_string, var->mbv_info_lvl + 1,
2237                         info_lvl_strings[var->mbv_info_lvl], pmix_var_type_names[var->mbv_type]);
2238         if (0 > ret) {
2239             return PMIX_ERR_OUT_OF_RESOURCE;
2240         }
2241 
2242         tmp = out[0][0];
2243         if (PMIX_VAR_IS_DEPRECATED(var[0])) {
2244             ret = asprintf (out[0], "%s, deprecated", tmp);
2245             free (tmp);
2246             if (0 > ret) {
2247                 return PMIX_ERR_OUT_OF_RESOURCE;
2248             }
2249             tmp = out[0][0];
2250         }
2251 
2252         /* Does this parameter have any synonyms or is it a synonym? */
2253         if (PMIX_VAR_IS_SYNONYM(var[0])) {
2254             ret = asprintf(out[0], "%s, synonym of: %s)", tmp, original->mbv_full_name);
2255             free (tmp);
2256             if (0 > ret) {
2257                 return PMIX_ERR_OUT_OF_RESOURCE;
2258             }
2259         } else if (synonym_count) {
2260             ret = asprintf(out[0], "%s, synonyms: ", tmp);
2261             free (tmp);
2262             if (0 > ret) {
2263                 return PMIX_ERR_OUT_OF_RESOURCE;
2264             }
2265 
2266             for (i = 0 ; i < synonym_count ; ++i) {
2267                 pmix_mca_base_var_t *synonym;
2268 
2269                 ret = var_get(synonyms[i], &synonym, false);
2270                 if (PMIX_SUCCESS != ret) {
2271                     continue;
2272                 }
2273 
2274                 tmp = out[0][0];
2275                 if (synonym_count == i+1) {
2276                     ret = asprintf(out[0], "%s%s)", tmp, synonym->mbv_full_name);
2277                 } else {
2278                     ret = asprintf(out[0], "%s%s, ", tmp, synonym->mbv_full_name);
2279                 }
2280                 free(tmp);
2281                 if (0 > ret) {
2282                     return PMIX_ERR_OUT_OF_RESOURCE;
2283                 }
2284             }
2285         } else {
2286             ret = asprintf(out[0], "%s)", tmp);
2287             free(tmp);
2288             if (0 > ret) {
2289                 return PMIX_ERR_OUT_OF_RESOURCE;
2290             }
2291         }
2292 
2293         line++;
2294 
2295         if (var->mbv_description) {
2296             ret = asprintf(out[0] + line++, "%s", var->mbv_description);
2297             if (0 > ret) {
2298                 return PMIX_ERR_OUT_OF_RESOURCE;
2299             }
2300         }
2301 
2302         if (NULL != var->mbv_enumerator) {
2303             char *values;
2304 
2305             ret = var->mbv_enumerator->dump(var->mbv_enumerator, &values);
2306             if (PMIX_SUCCESS == ret) {
2307                 ret = asprintf (out[0] + line++, "Valid values: %s", values);
2308                 free (values);
2309                 if (0 > ret) {
2310                     return PMIX_ERR_OUT_OF_RESOURCE;
2311                 }
2312             }
2313         }
2314     } else if (PMIX_MCA_BASE_VAR_DUMP_SIMPLE == output_type) {
2315         *out = (char **) calloc (2, sizeof (char *));
2316         if (NULL == *out) {
2317             free (value_string);
2318             free (source_string);
2319             return PMIX_ERR_OUT_OF_RESOURCE;
2320         }
2321 
2322         ret = asprintf(out[0], "%s=%s (%s)", var->mbv_full_name, value_string, source_string);
2323         if (0 > ret) {
2324             return PMIX_ERR_OUT_OF_RESOURCE;
2325         }
2326     }
2327 
2328     free (value_string);
2329     free (source_string);
2330 
2331     return PMIX_SUCCESS;
2332 }

/* [<][>][^][v][top][bottom][index][help] */