2005-03-14 23:57:21 +03:00
|
|
|
/*
|
2007-03-29 05:02:26 +04:00
|
|
|
* Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
|
2005-11-05 22:57:48 +03:00
|
|
|
* University Research and Technology
|
|
|
|
* Corporation. All rights reserved.
|
|
|
|
* Copyright (c) 2004-2005 The University of Tennessee and The University
|
|
|
|
* of Tennessee Research Foundation. All rights
|
|
|
|
* reserved.
|
2015-06-24 06:59:57 +03:00
|
|
|
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
|
2005-03-14 23:57:21 +03:00
|
|
|
* University of Stuttgart. All rights reserved.
|
2005-03-24 15:43:37 +03:00
|
|
|
* Copyright (c) 2004-2005 The Regents of the University of California.
|
|
|
|
* All rights reserved.
|
2015-02-12 21:54:08 +03:00
|
|
|
* Copyright (c) 2006-2015 Cisco Systems, Inc. All rights reserved.
|
2013-02-28 21:31:47 +04:00
|
|
|
* Copyright (c) 2007-2013 Los Alamos National Security, LLC. All rights
|
2014-11-05 03:11:15 +03:00
|
|
|
* reserved.
|
|
|
|
* Copyright (c) 2014 Intel, Inc. All rights reserved.
|
2005-03-14 23:57:21 +03:00
|
|
|
* $COPYRIGHT$
|
2015-06-24 06:59:57 +03:00
|
|
|
*
|
2005-03-14 23:57:21 +03:00
|
|
|
* Additional copyrights may follow
|
2015-06-24 06:59:57 +03:00
|
|
|
*
|
2005-03-14 23:57:21 +03:00
|
|
|
* $HEADER$
|
|
|
|
*/
|
|
|
|
|
2006-02-12 04:33:29 +03:00
|
|
|
#include "opal_config.h"
|
2005-03-14 23:57:21 +03:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2005-07-04 06:16:57 +04:00
|
|
|
#include "opal/util/printf.h"
|
2005-07-04 04:13:44 +04:00
|
|
|
#include "opal/util/argv.h"
|
2005-07-04 05:36:20 +04:00
|
|
|
#include "opal/util/opal_environ.h"
|
2006-02-12 04:33:29 +03:00
|
|
|
#include "opal/constants.h"
|
2005-03-14 23:57:21 +03:00
|
|
|
|
2015-06-24 06:59:57 +03:00
|
|
|
#define OPAL_DEFAULT_TMPDIR "/tmp"
|
2008-04-01 00:15:49 +04:00
|
|
|
|
2005-03-14 23:57:21 +03:00
|
|
|
/*
|
|
|
|
* Merge two environ-like char arrays, ensuring that there are no
|
|
|
|
* duplicate entires
|
|
|
|
*/
|
2005-07-04 05:36:20 +04:00
|
|
|
char **opal_environ_merge(char **minor, char **major)
|
2005-03-14 23:57:21 +03:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char **ret = NULL;
|
|
|
|
char *name, *value;
|
|
|
|
|
|
|
|
/* Check for bozo cases */
|
|
|
|
|
|
|
|
if (NULL == major) {
|
|
|
|
if (NULL == minor) {
|
|
|
|
return NULL;
|
|
|
|
} else {
|
2005-07-04 04:13:44 +04:00
|
|
|
return opal_argv_copy(minor);
|
2005-03-14 23:57:21 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* First, copy major */
|
|
|
|
|
2005-07-04 04:13:44 +04:00
|
|
|
ret = opal_argv_copy(major);
|
2005-03-14 23:57:21 +03:00
|
|
|
|
|
|
|
/* Do we have something in minor? */
|
|
|
|
|
|
|
|
if (NULL == minor) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2005-07-04 05:36:20 +04:00
|
|
|
/* Now go through minor and call opal_setenv(), but with overwrite
|
2005-03-14 23:57:21 +03:00
|
|
|
as false */
|
|
|
|
|
|
|
|
for (i = 0; NULL != minor[i]; ++i) {
|
|
|
|
value = strchr(minor[i], '=');
|
|
|
|
if (NULL == value) {
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_setenv(minor[i], NULL, false, &ret);
|
2005-03-14 23:57:21 +03:00
|
|
|
} else {
|
|
|
|
|
|
|
|
/* strdup minor[i] in case it's a constat string */
|
|
|
|
|
|
|
|
name = strdup(minor[i]);
|
|
|
|
value = name + (value - minor[i]);
|
|
|
|
*value = '\0';
|
2005-07-04 05:36:20 +04:00
|
|
|
opal_setenv(name, value + 1, false, &ret);
|
2005-03-14 23:57:21 +03:00
|
|
|
free(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* All done */
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Portable version of setenv(), allowing editing of any environ-like
|
|
|
|
* array
|
|
|
|
*/
|
2005-07-04 05:36:20 +04:00
|
|
|
int opal_setenv(const char *name, const char *value, bool overwrite,
|
2005-03-14 23:57:21 +03:00
|
|
|
char ***env)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char *newvalue, *compare;
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
/* Make the new value */
|
|
|
|
|
|
|
|
if (NULL == value) {
|
2015-02-12 21:54:08 +03:00
|
|
|
value = "";
|
2005-03-14 23:57:21 +03:00
|
|
|
asprintf(&newvalue, "%s=", name);
|
|
|
|
} else {
|
|
|
|
asprintf(&newvalue, "%s=%s", name, value);
|
|
|
|
}
|
|
|
|
if (NULL == newvalue) {
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERR_OUT_OF_RESOURCE;
|
2005-03-14 23:57:21 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Check the bozo case */
|
|
|
|
|
2006-08-23 03:25:13 +04:00
|
|
|
if( NULL == env ) {
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERR_BAD_PARAM;
|
2005-03-14 23:57:21 +03:00
|
|
|
} else if (NULL == *env) {
|
|
|
|
i = 0;
|
2005-07-04 04:13:44 +04:00
|
|
|
opal_argv_append(&i, env, newvalue);
|
2007-03-29 05:02:26 +04:00
|
|
|
free(newvalue);
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_SUCCESS;
|
2005-03-14 23:57:21 +03:00
|
|
|
}
|
|
|
|
|
2005-04-15 01:31:45 +04:00
|
|
|
/* If this is the "environ" array, use putenv */
|
2006-08-23 03:25:13 +04:00
|
|
|
if( *env == environ ) {
|
2005-04-15 01:31:45 +04:00
|
|
|
/* THIS IS POTENTIALLY A MEMORY LEAK! But I am doing it
|
2014-11-05 19:54:06 +03:00
|
|
|
so that we don't violate the law of least
|
2014-11-05 03:11:15 +03:00
|
|
|
astonishment for OPAL developers (i.e., those that don't
|
2005-07-04 05:36:20 +04:00
|
|
|
check the return code of opal_setenv() and notice that we
|
2005-04-15 01:31:45 +04:00
|
|
|
returned an error if you passed in the real environ) */
|
2014-11-05 03:11:15 +03:00
|
|
|
#if defined (HAVE_SETENV)
|
|
|
|
setenv(name, value, overwrite);
|
2014-11-05 19:54:06 +03:00
|
|
|
/* setenv copies the value, so we can free it here */
|
2014-11-05 03:11:15 +03:00
|
|
|
free(newvalue);
|
|
|
|
#else
|
2014-11-05 19:56:40 +03:00
|
|
|
len = strlen(name);
|
2014-11-05 19:54:06 +03:00
|
|
|
for (i = 0; (*env)[i] != NULL; ++i) {
|
|
|
|
if (0 == strncmp((*env)[i], name, len)) {
|
|
|
|
/* if we find the value in the environ, then
|
|
|
|
* we need to check the overwrite flag to determine
|
|
|
|
* the correct response */
|
|
|
|
if (overwrite) {
|
|
|
|
/* since it was okay to overwrite, do so */
|
|
|
|
putenv(newvalue);
|
|
|
|
/* putenv does NOT copy the value, so we
|
|
|
|
* cannot free it here */
|
|
|
|
return OPAL_SUCCESS;
|
|
|
|
}
|
|
|
|
/* since overwrite was not allowed, we return
|
|
|
|
* an error as we cannot perform the requested action */
|
|
|
|
free(newvalue);
|
|
|
|
return OPAL_EXISTS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* since the value wasn't found, we can add it */
|
2005-04-15 01:31:45 +04:00
|
|
|
putenv(newvalue);
|
2014-11-05 19:54:06 +03:00
|
|
|
/* putenv does NOT copy the value, so we
|
|
|
|
* cannot free it here */
|
2014-11-05 03:11:15 +03:00
|
|
|
#endif
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_SUCCESS;
|
2005-04-15 01:31:45 +04:00
|
|
|
}
|
|
|
|
|
2005-03-14 23:57:21 +03:00
|
|
|
/* Make something easy to compare to */
|
|
|
|
|
|
|
|
asprintf(&compare, "%s=", name);
|
|
|
|
if (NULL == compare) {
|
|
|
|
free(newvalue);
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERR_OUT_OF_RESOURCE;
|
2005-03-14 23:57:21 +03:00
|
|
|
}
|
|
|
|
len = strlen(compare);
|
|
|
|
|
|
|
|
/* Look for a duplicate that's already set in the env */
|
|
|
|
|
|
|
|
for (i = 0; (*env)[i] != NULL; ++i) {
|
|
|
|
if (0 == strncmp((*env)[i], compare, len)) {
|
|
|
|
if (overwrite) {
|
|
|
|
free((*env)[i]);
|
|
|
|
(*env)[i] = newvalue;
|
|
|
|
free(compare);
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_SUCCESS;
|
2005-03-14 23:57:21 +03:00
|
|
|
} else {
|
|
|
|
free(compare);
|
|
|
|
free(newvalue);
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_EXISTS;
|
2005-03-14 23:57:21 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If we found no match, append this value */
|
|
|
|
|
2005-07-04 04:13:44 +04:00
|
|
|
i = opal_argv_count(*env);
|
|
|
|
opal_argv_append(&i, env, newvalue);
|
2005-03-14 23:57:21 +03:00
|
|
|
|
|
|
|
/* All done */
|
|
|
|
|
|
|
|
free(compare);
|
|
|
|
free(newvalue);
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_SUCCESS;
|
2005-03-14 23:57:21 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Portable version of unsetenv(), allowing editing of any
|
|
|
|
* environ-like array
|
|
|
|
*/
|
2005-07-04 05:36:20 +04:00
|
|
|
int opal_unsetenv(const char *name, char ***env)
|
2005-03-14 23:57:21 +03:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char *compare;
|
|
|
|
size_t len;
|
|
|
|
bool found;
|
|
|
|
|
2005-04-05 02:03:37 +04:00
|
|
|
/* Check for bozo case */
|
|
|
|
|
|
|
|
if (NULL == *env) {
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_SUCCESS;
|
2005-04-05 02:03:37 +04:00
|
|
|
}
|
|
|
|
|
2005-03-14 23:57:21 +03:00
|
|
|
/* Make something easy to compare to */
|
|
|
|
|
|
|
|
asprintf(&compare, "%s=", name);
|
|
|
|
if (NULL == compare) {
|
2006-02-12 04:33:29 +03:00
|
|
|
return OPAL_ERR_OUT_OF_RESOURCE;
|
2005-03-14 23:57:21 +03:00
|
|
|
}
|
|
|
|
len = strlen(compare);
|
|
|
|
|
|
|
|
/* Look for a duplicate that's already set in the env. If we find
|
|
|
|
it, free it, and then start shifting all elements down one in
|
|
|
|
the array. */
|
|
|
|
|
|
|
|
found = false;
|
|
|
|
for (i = 0; (*env)[i] != NULL; ++i) {
|
2007-01-31 18:58:51 +03:00
|
|
|
if (0 != strncmp((*env)[i], compare, len))
|
|
|
|
continue;
|
|
|
|
if (environ != *env) {
|
|
|
|
free((*env)[i]);
|
|
|
|
}
|
|
|
|
for (; (*env)[i] != NULL; ++i)
|
2005-03-14 23:57:21 +03:00
|
|
|
(*env)[i] = (*env)[i + 1];
|
2007-01-31 18:58:51 +03:00
|
|
|
found = true;
|
|
|
|
break;
|
2005-03-14 23:57:21 +03:00
|
|
|
}
|
2006-10-21 17:46:04 +04:00
|
|
|
free(compare);
|
2005-03-14 23:57:21 +03:00
|
|
|
|
|
|
|
/* All done */
|
|
|
|
|
2006-02-12 04:33:29 +03:00
|
|
|
return (found) ? OPAL_SUCCESS : OPAL_ERR_NOT_FOUND;
|
2005-03-14 23:57:21 +03:00
|
|
|
}
|
2007-01-31 18:58:51 +03:00
|
|
|
|
2008-03-13 20:56:44 +03:00
|
|
|
const char* opal_tmp_directory( void )
|
|
|
|
{
|
|
|
|
const char* str;
|
|
|
|
|
|
|
|
if( NULL == (str = getenv("TMPDIR")) )
|
|
|
|
if( NULL == (str = getenv("TEMP")) )
|
|
|
|
if( NULL == (str = getenv("TMP")) )
|
2008-04-01 01:42:59 +04:00
|
|
|
str = OPAL_DEFAULT_TMPDIR;
|
2008-03-13 20:56:44 +03:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* opal_home_directory( void )
|
|
|
|
{
|
|
|
|
char* home = getenv("HOME");
|
|
|
|
|
|
|
|
return home;
|
|
|
|
}
|
|
|
|
|