Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add rcutils_set_env function #250

Merged
merged 8 commits into from
May 20, 2020
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ set(rcutils_sources
src/array_list.c
src/char_array.c
src/cmdline_parser.c
src/env.c
src/error_handling.c
src/filesystem.c
src/find.c
Expand Down Expand Up @@ -291,6 +292,13 @@ if(BUILD_TESTING)
target_link_libraries(test_get_env ${PROJECT_NAME})
endif()

rcutils_custom_add_gtest(test_env test/test_env.cpp
APPEND_LIBRARY_DIRS "$<TARGET_FILE_DIR:${PROJECT_NAME}>"
)
if(TARGET test_env)
target_link_libraries(test_env ${PROJECT_NAME})
endif()

rcutils_custom_add_gtest(test_filesystem
test/test_filesystem.cpp
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,11 @@ The API is a combination of parts:
- A convenient string formatting function, which takes a custom allocator:
- rcutils_format_string()
- rcutils/format_string.h
- A function to get an environment variable's value:
- Functions for interfacing with process environment variables:
- rcutils_get_env()
- rcutils_get_home_dir()
- rcutils_set_env()
- rcutils/env.h
- rcutils/get_env.h
- Extensible logging macros:
- Some examples (not exhaustive):
Expand Down
64 changes: 64 additions & 0 deletions include/rcutils/env.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright 2020 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef RCUTILS__ENV_H_
#define RCUTILS__ENV_H_

#ifdef __cplusplus
extern "C"
{
#endif

#include <stdbool.h>

#include "rcutils/macros.h"
#include "rcutils/visibility_control.h"

// TODO(cottsay): Deprecate get_env.h and eventually merge it here
#include "rcutils/get_env.h"

/// Set or un-set a process-scoped environment variable.
/**
* This function modifies the environment variables for the current process by
* copying given string values into the process' global environment variable
* store.
*
* \par Thread Safety:
* This function is not thread-safe, particularly when called concurrently with
* ::rcutils_get_env. Take care not to modify the environment variables while
* another thread might be reading or writing environment variables.
*
* \par Platform Consistency:
* The behavior when setting a variable to an empty string (`""`) differs
* between platforms. On Windows, the variable is un-set (as if \p env_value was
* `NULL`), while on other platforms the variable is set to an empty string as
* expected.
*
* \param[in] env_name Name of the environment variable to modify.
* \param[in] env_value Value to set the environment variable to, or `NULL` to
* un-set.
* \return `True` if success
* \return `False` if env_name is invalid or NULL
* \return `False` on failure
*/
RCUTILS_PUBLIC
RCUTILS_WARN_UNUSED
bool
rcutils_set_env(const char * env_name, const char * env_value);

#ifdef __cplusplus
}
#endif

#endif // RCUTILS__ENV_H_
61 changes: 61 additions & 0 deletions src/env.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright 2020 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifdef __cplusplus
extern "C"
{
#endif

#include <errno.h>
#include <stdlib.h>

#include "rcutils/env.h"
#include "rcutils/error_handling.h"

// TODO(cottsay): Move the stuff in get_env.c in here

bool
rcutils_set_env(const char * env_name, const char * env_value)
{
RCUTILS_CHECK_FOR_NULL_WITH_MSG(
env_name, "env_name is null", return false);

#ifdef _WIN32
if (NULL == env_value) {
env_value = "";
}
if (0 != _putenv_s(env_name, env_value)) {
cottsay marked this conversation as resolved.
Show resolved Hide resolved
RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING("_putenv_s failed: %d", errno);
return false;
}
#else
if (NULL == env_value) {
if (0 != unsetenv(env_name)) {
RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING("unsetenv failed: %d", errno);
return false;
cottsay marked this conversation as resolved.
Show resolved Hide resolved
}
} else {
if (0 != setenv(env_name, env_value, 1)) {
cottsay marked this conversation as resolved.
Show resolved Hide resolved
RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING("setenv failed: %d", errno);
return false;
}
}
#endif

return true;
}

#ifdef __cplusplus
}
#endif
53 changes: 53 additions & 0 deletions test/test_env.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2020 Open Source Robotics Foundation, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <gtest/gtest.h>

#include <string>

#include "rcutils/env.h"
#include "rcutils/get_env.h"

TEST(TestEnv, test_set_env) {
const char * res = nullptr;

// Invalid cases
EXPECT_FALSE(rcutils_set_env(nullptr, nullptr));
cottsay marked this conversation as resolved.
Show resolved Hide resolved
EXPECT_FALSE(rcutils_set_env("=INVALID_ENV_VAR=", nullptr));
EXPECT_FALSE(rcutils_set_env("=INVALID_ENV_VAR=", "InvalidEnvValue"));

// Ensure we're starting clean
ASSERT_EQ(nullptr, rcutils_get_env("NEW_ENV_VAR", &res));
ASSERT_STREQ("", res);

// Simple set
ASSERT_TRUE(rcutils_set_env("NEW_ENV_VAR", "NewEnvValue"));
ASSERT_STREQ(nullptr, rcutils_get_env("NEW_ENV_VAR", &res));
EXPECT_STREQ(res, "NewEnvValue");

// Re-set
ASSERT_TRUE(rcutils_set_env("NEW_ENV_VAR", "DifferentEnvValue"));
ASSERT_STREQ(nullptr, rcutils_get_env("NEW_ENV_VAR", &res));
EXPECT_STREQ(res, "DifferentEnvValue");

// Un-set
ASSERT_TRUE(rcutils_set_env("NEW_ENV_VAR", nullptr));
ASSERT_EQ(nullptr, rcutils_get_env("NEW_ENV_VAR", &res));
EXPECT_STREQ("", res);

// Un-set again
ASSERT_TRUE(rcutils_set_env("NEW_ENV_VAR", nullptr));
ASSERT_EQ(nullptr, rcutils_get_env("NEW_ENV_VAR", &res));
EXPECT_STREQ("", res);
}