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 in utilities needed for log location #155

Merged
merged 10 commits into from
May 6, 2019
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ set(rcutils_sources
src/get_env.c
src/hash_map.c
src/logging.c
src/process.c
src/repl_str.c
src/snprintf.c
src/split.c
Expand Down
24 changes: 24 additions & 0 deletions include/rcutils/get_env.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,30 @@ RCUTILS_WARN_UNUSED
const char *
rcutils_get_env(const char * env_name, const char ** env_value);

/// Retrieve the full path to the home directory.
/*
wjwwood marked this conversation as resolved.
Show resolved Hide resolved
* The c-string which is returned is only valid until the next time this
* function is called, because it is a direct pointer to the static storage.
* Also note that the string returned here should *not* be freed.
*
* The function first tries to get the HOME environment variable.
* If that variable exists and is non-empty, that will be returned.
* Otherwise, the function tries to get the USERPROFILE environment variable.
* If that variable exists and is non-empty, that will be returned.
* If neither exists, NULL will be returned.
* The above algorithm is portable across both Unix and Windows.
*
* The home directory will be truncated at 2048 characters on Windows.
*
* This function is not thread-safe.
*
* \return The home directory on success, NULL on failure.
*/
RCUTILS_PUBLIC
RCUTILS_WARN_UNUSED
wjwwood marked this conversation as resolved.
Show resolved Hide resolved
const char *
rcutils_get_home_dir(void);

#ifdef __cplusplus
}
#endif
Expand Down
58 changes: 58 additions & 0 deletions include/rcutils/process.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright 2019 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__PROCESS_H_
#define RCUTILS__PROCESS_H_

#ifdef __cplusplus
extern "C"
{
#endif

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

/// Retrieve the current process ID.
/*
* This function returns the current process ID, and is always successful.
*
* This function is thread-safe.
*
* \return The current process ID.
*/
RCUTILS_PUBLIC
RCUTILS_WARN_UNUSED
int rcutils_get_pid(void);

/// Retrieve the current executable name.
/*
* This function portably retrieves the current program name and returns
* a copy of it.
* It is up to the caller to free the memory.
*
* This function is thread-safe.
*
* \param[in] allocator the allocator to use
* \return The program name on success, NULL on failure.
*/
RCUTILS_PUBLIC
RCUTILS_WARN_UNUSED
char * rcutils_get_executable_name(rcutils_allocator_t allocator);

#ifdef __cplusplus
}
#endif

#endif // RCUTILS__PROCESS_H_
22 changes: 22 additions & 0 deletions src/get_env.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,28 @@ rcutils_get_env(const char * env_name, const char ** env_value)
return NULL;
}

const char *
rcutils_get_home_dir(void)
{
const char * homedir;

if (rcutils_get_env("HOME", &homedir) == NULL && *homedir != '\0') {
// The HOME environment variable was set and is non-empty, return it.
return homedir;
}

#ifdef _WIN32
// We didn't find a HOME variable, try USERPROFILE on Windows.
if (rcutils_get_env("USERPROFILE", &homedir) == NULL && *homedir != '\0') {
// The USERPROFILE environment variable was set and is non-empty, return it.
return homedir;
}
#endif

// Couldn't get the home directory, return NULL.
return NULL;
}

#ifdef __cplusplus
}
#endif
103 changes: 103 additions & 0 deletions src/process.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright 2019 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

#define _GNU_SOURCE
#include <errno.h>
#include <stdlib.h>
#include <string.h>

#if defined _WIN32 || defined __CYGWIN__
#include <Windows.h>
#else
#include <unistd.h>
#endif

#include "rcutils/allocator.h"
#include "rcutils/error_handling.h"
#include "rcutils/process.h"

int rcutils_get_pid(void)
{
#if defined _WIN32 || defined __CYGWIN__
return (int)GetCurrentProcessId();
#else
return (int)getpid();
#endif
}

char * rcutils_get_executable_name(rcutils_allocator_t allocator)
{
RCUTILS_CHECK_ALLOCATOR_WITH_MSG(
&allocator, "invalid allocator", return NULL);

#if defined __APPLE__
const char * appname = getprogname();
#elif defined __GNUC__
const char * appname = program_invocation_name;
#elif defined _WIN32 || defined __CYGWIN
char appname[MAX_PATH];
int32_t size = GetModuleFileNameA(NULL, appname, MAX_PATH);
if (size == 0) {
return NULL;
}
#else
#error "Unsupported OS"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't found examples of other cross-platform code where we explicitly error in fall-through cases. I don't know if that's because other code is structured to assume Linux/Unix in the fall-through case or if runtime errors are being used instead.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had more to say about this, but GitHub deleted my review... I'm fine with it as-is.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had more to say about this, but GitHub deleted my review...

:rage4:

#endif

size_t applen = strlen(appname);

// Since the above memory may be static, and the caller may want to modify
// the argument, make and return a copy here.
char * basec = allocator.allocate(applen + 1, allocator.state);
if (NULL == basec) {
return NULL;
}

// Get just the executable name (Unix may return the absolute path)
#if defined __APPLE__ || defined __GNUC__
// We need an intermediate copy because basename may modify its arguments
char * intermediate = allocator.allocate(applen + 1, allocator.state);
if (NULL == intermediate) {
allocator.deallocate(basec, allocator.state);
return NULL;
}
memcpy(intermediate, appname, applen);
intermediate[applen] = '\0';

char * bname = basename(intermediate);
size_t baselen = strlen(bname);
memcpy(basec, bname, baselen);
basec[baselen] = '\0';
allocator.deallocate(intermediate, allocator.state);
#elif defined _WIN32 || defined __CYGWIN
errno_t err = _splitpath_s(appname, NULL, 0, NULL, 0, basec, applen, NULL, 0);
if (err != 0) {
allocator.deallocate(basec, allocator.state);
return NULL;
}
#else
#error "Unsupported OS"
#endif

return basec;
}

#ifdef __cplusplus
}
#endif