You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
pEpEngine/src/platform_unix.c

967 lines
27 KiB
C

/**
* @file platform_unix.c
* @brief File description for doxygen missing. FIXME
* @license This file is under GNU General Public License 3.0. - see LICENSE.txt
*/
#ifndef __MVS__
#define _POSIX_C_SOURCE 200809L
#endif
#ifdef ANDROID
#ifndef __LP64__
#include <time64.h>
#endif
#endif
4 years ago
#include <stdbool.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
4 years ago
#include <stdio.h>
#include <glob.h>
4 years ago
#include <errno.h>
#include <sys/stat.h>
8 years ago
#include <sys/types.h>
#include <fcntl.h>
7 years ago
#include <regex.h>
8 years ago
fix ENGINE-956 It is now possible to use shell environment variables in PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY, expanded at *run* time. This is meant to allow more freedom to the deployment engineer, without affecting development. Notice that, when PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY are defined in the Makefile, dollar signs must be escaped (a dollar becomes a double dollar) because of *make* syntax: this has nothing to do with pEp engine code. Expansion follows the Unix shell $VARIABLE syntax: ${VARIABLE} is not supported. See _expand_variables. src/platform_unix.c contained some duplicated logic about caching path results into static variables; this change set would have added to the complexity by calling the new path expansion function, in many different places. Seize the occasion for factoring. Do not change the meaning of PER_USER_DIRECTORY yet; I would like to do it, since it is confusing and inconsistent with per_user_directory (PER_USER_DIRECTORY is a relative path on Unix, while per_user_directory is absolute), but the actual semantics with respect to $HOME and $PEP_HOME is complicated and I do not want to break it. New API function per_user_relative_directory. Remove the ugly "reset" argument from unix_local_db (which was conditionally defined according to NDEBUG!), used to force path re-computation in the test suite after changing an environment variable so as to work in a new "home" directory. In the place of this reset argument add clear API functions to the engine for handling the cache. My quick grapping and IRC interaction confirm that nobody was using the functionality out of the engine test suite. Adapt the test suite to use the new API. Tentatively add caching and expansion functionality to android_system_db as well.
2 years ago
#include "pEpEngine.h" /* For PEP_STATUS */
#include "platform_unix.h"
4 years ago
#include "dynamic_api.h"
#define MAX_PATH 1024
#ifndef LOCAL_DB_FILENAME
#define OLD_LOCAL_DB_FILENAME ".pEp_management.db"
#define OLD_KEYS_DB_FILENAME ".pEp_keys.db"
#define LOCAL_DB_FILENAME "management.db"
#define KEYS_DB_FILENAME "keys.db"
#endif
#define SYSTEM_DB_FILENAME "system.db"
#ifndef strndup
char *strndup (const char *s, size_t n)
{
char *result;
size_t len = strnlen (s, n);
result = (char *) malloc (len + 1);
if (!result)
return 0;
result[len] = '\0';
return (char *) memcpy (result, s, len);
}
#endif
#ifndef strnlen
size_t strnlen (const char *s, size_t maxlen)
{
size_t i;
for (i = 0; i < maxlen; ++i)
if (s[i] == '\0')
break;
return i;
}
#endif
#ifndef stpcpy
char *stpcpy(char *dst, const char *src)
{
for (;; ++dst, ++src) {
*dst = *src;
if (*dst == 0)
break;
}
return dst;
}
#endif
#ifndef alloca
#pragma linkage(__alloca,builtin)
void *__alloca(unsigned long x);
void *alloca(unsigned long x)
{
return __alloca(x);
}
#endif
#if defined(ANDROID) || defined(__MVS__)
/* FIXME : timegm will miss when linking for x86_64 on android, when supported */
#ifndef __LP64__
time_t timegm(struct tm* const t) {
static const time_t kTimeMax = ~(1L << (sizeof(time_t) * CHAR_BIT - 1));
static const time_t kTimeMin = (1L << (sizeof(time_t) * CHAR_BIT - 1));
time64_t result = timegm64(t);
if (result < kTimeMin || result > kTimeMax)
return -1;
return result;
}
#endif
char *stpncpy(char *dst, const char *src, size_t n)
{
if (n != 0) {
char *d = dst;
const char *s = src;
dst = &dst[n];
do {
if ((*d++ = *s++) == 0) {
dst = d - 1;
/* NUL pad the remaining n-1 bytes */
while (--n != 0)
*d++ = 0;
break;
}
} while (--n != 0);
}
return (dst);
}
/*
long int random(void)
{
static bool seeded = false;
static unsigned short xsubi[3];
if(!seeded)
{
const long long t = (long long)time(NULL);
xsubi[0] = (unsigned short)t;
xsubi[1] = (unsigned short)(t>>16);
xsubi[2] = (unsigned short)(t>>32);
seeded = true;
}
return nrand48(xsubi);
} */
fix ENGINE-956 It is now possible to use shell environment variables in PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY, expanded at *run* time. This is meant to allow more freedom to the deployment engineer, without affecting development. Notice that, when PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY are defined in the Makefile, dollar signs must be escaped (a dollar becomes a double dollar) because of *make* syntax: this has nothing to do with pEp engine code. Expansion follows the Unix shell $VARIABLE syntax: ${VARIABLE} is not supported. See _expand_variables. src/platform_unix.c contained some duplicated logic about caching path results into static variables; this change set would have added to the complexity by calling the new path expansion function, in many different places. Seize the occasion for factoring. Do not change the meaning of PER_USER_DIRECTORY yet; I would like to do it, since it is confusing and inconsistent with per_user_directory (PER_USER_DIRECTORY is a relative path on Unix, while per_user_directory is absolute), but the actual semantics with respect to $HOME and $PEP_HOME is complicated and I do not want to break it. New API function per_user_relative_directory. Remove the ugly "reset" argument from unix_local_db (which was conditionally defined according to NDEBUG!), used to force path re-computation in the test suite after changing an environment variable so as to work in a new "home" directory. In the place of this reset argument add clear API functions to the engine for handling the cache. My quick grapping and IRC interaction confirm that nobody was using the functionality out of the engine test suite. Adapt the test suite to use the new API. Tentatively add caching and expansion functionality to android_system_db as well.
2 years ago
/* This is a non-caching function: see the comments in "Internal path caching
functionality" below. */
static char *_android_system_db(void)
{
fix ENGINE-956 It is now possible to use shell environment variables in PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY, expanded at *run* time. This is meant to allow more freedom to the deployment engineer, without affecting development. Notice that, when PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY are defined in the Makefile, dollar signs must be escaped (a dollar becomes a double dollar) because of *make* syntax: this has nothing to do with pEp engine code. Expansion follows the Unix shell $VARIABLE syntax: ${VARIABLE} is not supported. See _expand_variables. src/platform_unix.c contained some duplicated logic about caching path results into static variables; this change set would have added to the complexity by calling the new path expansion function, in many different places. Seize the occasion for factoring. Do not change the meaning of PER_USER_DIRECTORY yet; I would like to do it, since it is confusing and inconsistent with per_user_directory (PER_USER_DIRECTORY is a relative path on Unix, while per_user_directory is absolute), but the actual semantics with respect to $HOME and $PEP_HOME is complicated and I do not want to break it. New API function per_user_relative_directory. Remove the ugly "reset" argument from unix_local_db (which was conditionally defined according to NDEBUG!), used to force path re-computation in the test suite after changing an environment variable so as to work in a new "home" directory. In the place of this reset argument add clear API functions to the engine for handling the cache. My quick grapping and IRC interaction confirm that nobody was using the functionality out of the engine test suite. Adapt the test suite to use the new API. Tentatively add caching and expansion functionality to android_system_db as well.
2 years ago
char *buffer = malloc (MAX_PATH);
if (buffer == NULL)
return NULL;
char *tw_env;
if(tw_env = getenv("TRUSTWORDS")){
char *p = stpncpy(buffer, tw_env, MAX_PATH);
ssize_t len = MAX_PATH - (p - buffer) - 2;
fix ENGINE-956 It is now possible to use shell environment variables in PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY, expanded at *run* time. This is meant to allow more freedom to the deployment engineer, without affecting development. Notice that, when PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY are defined in the Makefile, dollar signs must be escaped (a dollar becomes a double dollar) because of *make* syntax: this has nothing to do with pEp engine code. Expansion follows the Unix shell $VARIABLE syntax: ${VARIABLE} is not supported. See _expand_variables. src/platform_unix.c contained some duplicated logic about caching path results into static variables; this change set would have added to the complexity by calling the new path expansion function, in many different places. Seize the occasion for factoring. Do not change the meaning of PER_USER_DIRECTORY yet; I would like to do it, since it is confusing and inconsistent with per_user_directory (PER_USER_DIRECTORY is a relative path on Unix, while per_user_directory is absolute), but the actual semantics with respect to $HOME and $PEP_HOME is complicated and I do not want to break it. New API function per_user_relative_directory. Remove the ugly "reset" argument from unix_local_db (which was conditionally defined according to NDEBUG!), used to force path re-computation in the test suite after changing an environment variable so as to work in a new "home" directory. In the place of this reset argument add clear API functions to the engine for handling the cache. My quick grapping and IRC interaction confirm that nobody was using the functionality out of the engine test suite. Adapt the test suite to use the new API. Tentatively add caching and expansion functionality to android_system_db as well.
2 years ago
if (len < strlen(SYSTEM_DB_FILENAME)) {
assert(0);
return NULL;
}
fix ENGINE-956 It is now possible to use shell environment variables in PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY, expanded at *run* time. This is meant to allow more freedom to the deployment engineer, without affecting development. Notice that, when PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY are defined in the Makefile, dollar signs must be escaped (a dollar becomes a double dollar) because of *make* syntax: this has nothing to do with pEp engine code. Expansion follows the Unix shell $VARIABLE syntax: ${VARIABLE} is not supported. See _expand_variables. src/platform_unix.c contained some duplicated logic about caching path results into static variables; this change set would have added to the complexity by calling the new path expansion function, in many different places. Seize the occasion for factoring. Do not change the meaning of PER_USER_DIRECTORY yet; I would like to do it, since it is confusing and inconsistent with per_user_directory (PER_USER_DIRECTORY is a relative path on Unix, while per_user_directory is absolute), but the actual semantics with respect to $HOME and $PEP_HOME is complicated and I do not want to break it. New API function per_user_relative_directory. Remove the ugly "reset" argument from unix_local_db (which was conditionally defined according to NDEBUG!), used to force path re-computation in the test suite after changing an environment variable so as to work in a new "home" directory. In the place of this reset argument add clear API functions to the engine for handling the cache. My quick grapping and IRC interaction confirm that nobody was using the functionality out of the engine test suite. Adapt the test suite to use the new API. Tentatively add caching and expansion functionality to android_system_db as well.
2 years ago
*p++ = '/';
strncpy(p, SYSTEM_DB_FILENAME, len);
}else{
return NULL;
}
return buffer;
}
#endif
#ifdef __MVS__
char * e2as(const char * str)
{
char *ret = (char *)malloc(strlen(str));
strcpy(ret, str);
__e2a_s(ret);
return ret;
}
char * as2e(const char * str)
{
char *ret = (char *)malloc(strlen(str));
strcpy(ret, str);
__a2e_s(ret);
return ret;
}
void uuid_generate_random(pEpUUID out)
{
}
void uuid_unparse_upper(pEpUUID uu, uuid_string_t out)
{
}
#endif
#ifdef ANDROID
void uuid_generate_random(pEpUUID out)
{
uuid_t *uuid;
uuid_rc_t rc_create;
size_t size = sizeof(uuid_string_t);
void *_out = out;
if ((rc_create = uuid_create(&uuid)) != UUID_RC_OK ||
uuid_make(uuid, UUID_MAKE_V1) != UUID_RC_OK ||
uuid_export(uuid, UUID_FMT_BIN, &_out, &size) != UUID_RC_OK)
{
memset(out, 0, sizeof(pEpUUID));
}
if (rc_create == UUID_RC_OK)
{
uuid_destroy(uuid);
}
}
void uuid_unparse_upper(pEpUUID uu, uuid_string_t out)
{
uuid_t *uuid;
uuid_rc_t rc_create;
size_t size = sizeof(uuid_string_t);
void *_out = out;
if ((rc_create = uuid_create(&uuid)) != UUID_RC_OK ||
uuid_import(uuid, UUID_FMT_BIN, uu, sizeof(pEpUUID)) != UUID_RC_OK ||
uuid_export(uuid, UUID_FMT_STR, &_out, &size) != UUID_RC_OK)
{
memset(out, 0, sizeof(uuid_string_t));
}
else
{
out[sizeof(uuid_string_t) - 1] = 0;
}
if (rc_create == UUID_RC_OK)
{
uuid_destroy(uuid);
}
}
#endif
#if !defined(BSD) && !defined(__APPLE__)
size_t strlcpy(char* dst, const char* src, size_t size) {
size_t retval = strlen(src);
size_t size_to_copy = (retval < size ? retval : size - 1);
// strlcpy doc says src and dst not allowed to overlap, as
// it's undefined. So this is acceptable:
memcpy((void*)dst, (void*)src, size_to_copy); // no defined error return, but strcpy doesn't either
dst[size_to_copy] = '\0';
return retval;
}
size_t strlcat(char* dst, const char* src, size_t size) {
size_t start_len = strnlen(dst, size);
if (start_len == size)
return size; // no copy, no null termination in size bytes, according to spec
size_t add_len = strlen(src);
size_t retval = start_len + add_len;
size_t size_to_copy = (retval < size ? add_len : (size - start_len) - 1);
// strlcat doc says src and dst not allowed to overlap, as
// it's undefined. So this is acceptable:
memcpy((void*)(dst + start_len), (void*)src, size_to_copy); // no defined error return, but strcpy doesn't either
dst[start_len + size_to_copy] = '\0';
return retval;
}
char *strnstr(const char *big, const char *little, size_t len) {
if (big == NULL || little == NULL)
return NULL;
if (*little == '\0')
return (char*)big;
const char* curr_big = big;
size_t little_len = strlen(little);
size_t remaining = len;
const char* retval = NULL;
for (remaining = len; remaining >= little_len && *curr_big != '\0'; remaining--, curr_big++) {
// find first-char match
if (*curr_big != *little) {
continue;
}
retval = curr_big;
const char* inner_big = retval + 1;
const char* curr_little = little + 1;
int j;
for (j = 1; j < little_len; j++, inner_big++, curr_little++) {
if (*inner_big != *curr_little) {
retval = NULL;
break;
}
}
if (retval)
break;
}
return (char*)retval;
}
// #ifdef USE_NETPGP
// // FIXME: This may cause problems - this is a quick compatibility fix for netpgp code
// int regnexec(const regex_t* preg, const char* string,
// size_t len, size_t nmatch, regmatch_t pmatch[], int eflags) {
// return regexec(preg, string, nmatch, pmatch, eflags);
// }
// #endif
7 years ago
#endif
/**
* @internal
*
* <!-- _stradd() -->
*
* @brief TODO
*
* @param[in] **first char
* @param[in] *second constchar
*
*/
static char *_stradd(char **first, const char *second)
{
assert(first && *first && second);
if (!(first && *first && second))
return NULL;
size_t len1 = strlen(*first);
size_t len2 = strlen(second);
size_t size = len1 + len2 + 1;
char *_first = realloc(*first, size);
assert(_first);
if (!_first)
return NULL;
*first = _first;
strlcat(*first, second, size);
return *first;
}
/**
* @internal
*
* <!-- _empty() -->
*
* @brief TODO
*
* @param[in] **p char
*
*/
static void _empty(char **p)
{
free(*p);
*p = NULL;
}
/**
* @internal
*
* <!-- _move() -->
*
* @brief TODO
*
* @param[in] *o constchar
* @param[in] *ext constchar
* @param[in] *n constchar
*
*/
static void _move(const char *o, const char *ext, const char *n)
{
assert(o && ext && n);
if (!(o && ext && n))
return;
char *_old = strdup(o);
assert(_old);
if (!_old)
return;
char *r = _stradd(&_old, ext);
if (!r) {
free(_old);
return;
}
char *_new = strdup(n);
assert(_new);
if (!_new) {
free(_old);
return;
}
r = _stradd(&_new, ext);
if (r)
rename(_old, _new);
free(_old);
free(_new);
}
fix ENGINE-956 It is now possible to use shell environment variables in PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY, expanded at *run* time. This is meant to allow more freedom to the deployment engineer, without affecting development. Notice that, when PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY are defined in the Makefile, dollar signs must be escaped (a dollar becomes a double dollar) because of *make* syntax: this has nothing to do with pEp engine code. Expansion follows the Unix shell $VARIABLE syntax: ${VARIABLE} is not supported. See _expand_variables. src/platform_unix.c contained some duplicated logic about caching path results into static variables; this change set would have added to the complexity by calling the new path expansion function, in many different places. Seize the occasion for factoring. Do not change the meaning of PER_USER_DIRECTORY yet; I would like to do it, since it is confusing and inconsistent with per_user_directory (PER_USER_DIRECTORY is a relative path on Unix, while per_user_directory is absolute), but the actual semantics with respect to $HOME and $PEP_HOME is complicated and I do not want to break it. New API function per_user_relative_directory. Remove the ugly "reset" argument from unix_local_db (which was conditionally defined according to NDEBUG!), used to force path re-computation in the test suite after changing an environment variable so as to work in a new "home" directory. In the place of this reset argument add clear API functions to the engine for handling the cache. My quick grapping and IRC interaction confirm that nobody was using the functionality out of the engine test suite. Adapt the test suite to use the new API. Tentatively add caching and expansion functionality to android_system_db as well.
2 years ago
/**
* @internal
*
* <!-- _strdup_or_NULL() -->
*
* @brief Return a malloc-allocated copy of the given string, or (this
* is the added functionality with respect to the standard
* strdup) a malloc-allocated copy of "" if the argument is
* NULL.
* Return NULL only in case of an out-of-memory error.
fix ENGINE-956 It is now possible to use shell environment variables in PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY, expanded at *run* time. This is meant to allow more freedom to the deployment engineer, without affecting development. Notice that, when PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY are defined in the Makefile, dollar signs must be escaped (a dollar becomes a double dollar) because of *make* syntax: this has nothing to do with pEp engine code. Expansion follows the Unix shell $VARIABLE syntax: ${VARIABLE} is not supported. See _expand_variables. src/platform_unix.c contained some duplicated logic about caching path results into static variables; this change set would have added to the complexity by calling the new path expansion function, in many different places. Seize the occasion for factoring. Do not change the meaning of PER_USER_DIRECTORY yet; I would like to do it, since it is confusing and inconsistent with per_user_directory (PER_USER_DIRECTORY is a relative path on Unix, while per_user_directory is absolute), but the actual semantics with respect to $HOME and $PEP_HOME is complicated and I do not want to break it. New API function per_user_relative_directory. Remove the ugly "reset" argument from unix_local_db (which was conditionally defined according to NDEBUG!), used to force path re-computation in the test suite after changing an environment variable so as to work in a new "home" directory. In the place of this reset argument add clear API functions to the engine for handling the cache. My quick grapping and IRC interaction confirm that nobody was using the functionality out of the engine test suite. Adapt the test suite to use the new API. Tentatively add caching and expansion functionality to android_system_db as well.
2 years ago
*
* @param[in] *original constchar
* @retval NULL out of memory
* @retval non-NULL malloc-allocated buffer
*/
static char *_strdup_or_NULL(const char *original)
{
if (original == NULL)
original = "";
return strdup (original);
}
/*
* Environment variable expansion
* **********************************************************************
*/
/* The state of a DFA implementing variable recognition in _expand_variables ,
below. */
enum _expand_variable_state {
_expand_variable_state_non_variable,
_expand_variable_state_after_dollar,
_expand_variable_state_after_backslash,
_expand_variable_state_in_variable
};
/**
* @internal
*
* <!-- _expand_variables() -->
*
* @brief Set a malloc-allocated '\0'-terminated string which is
* a copy of the argument with shell variables expanded, where
* variable references use Unix shell-style syntax $VARIABLE.
* Notice that the alternative syntax ${VARIABLE} is not
* supported.
* See [FIXME: deployment-engineer documentation].
*
* @param[in] string_with_variables char *
* @param[out] out char** copy with variables expanded
fix ENGINE-956 It is now possible to use shell environment variables in PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY, expanded at *run* time. This is meant to allow more freedom to the deployment engineer, without affecting development. Notice that, when PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY are defined in the Makefile, dollar signs must be escaped (a dollar becomes a double dollar) because of *make* syntax: this has nothing to do with pEp engine code. Expansion follows the Unix shell $VARIABLE syntax: ${VARIABLE} is not supported. See _expand_variables. src/platform_unix.c contained some duplicated logic about caching path results into static variables; this change set would have added to the complexity by calling the new path expansion function, in many different places. Seize the occasion for factoring. Do not change the meaning of PER_USER_DIRECTORY yet; I would like to do it, since it is confusing and inconsistent with per_user_directory (PER_USER_DIRECTORY is a relative path on Unix, while per_user_directory is absolute), but the actual semantics with respect to $HOME and $PEP_HOME is complicated and I do not want to break it. New API function per_user_relative_directory. Remove the ugly "reset" argument from unix_local_db (which was conditionally defined according to NDEBUG!), used to force path re-computation in the test suite after changing an environment variable so as to work in a new "home" directory. In the place of this reset argument add clear API functions to the engine for handling the cache. My quick grapping and IRC interaction confirm that nobody was using the functionality out of the engine test suite. Adapt the test suite to use the new API. Tentatively add caching and expansion functionality to android_system_db as well.
2 years ago
* @retval PEP_STATUS_OK success
* @retval PEP_UNBOUND_ENVIRONMENT_VARIABLE unknown variable referenced
* @retval PEP_PATH_SYNTAX_ERROR invalid syntax in argument
* @retval PEP_OUT_OF_MEMORY out of memory
*
*/
static PEP_STATUS _expand_variables(char **out,
const char *string_with_variables)
{
PEP_STATUS res = PEP_STATUS_OK;
size_t in_length = strlen(string_with_variables);
const char *variable_name_beginning; /* This points within the input. */
char *variable_name_copy = NULL /* we free on error. */;
size_t allocated_size
#ifdef NDEBUG
= 1024;
#else
= 1 /* Notice that 0 is incorrect: this grows by doubling. */;
#endif // #ifdef NDEBUG
int out_index = 0; /* The out index is also the used out size */
const char *in = string_with_variables;
/* In the pEp engine we adopt the convention of "" behaving the same as
NULL. Notice that we never free this, so it is not a problem if this
string is not malloc-allocated. */
if (in == NULL)
in = "";
/* We free on error. */
* out = NULL ;
/* Recognise a variable according to POSIX syntax which, luckily for us,
only allows for letters, digits and underscores -- The first character
may not be a digit... */
#define VALID_FIRST_CHARACTER_FOR_VARIABLE(c) \
( ((c) >= 'a' && (c) <= 'z') \
|| ((c) >= 'A' && (c) <= 'Z') \
|| ((c) == '_'))
/* ...But characters after the first may be. */
#define VALID_NON_FIRST_CHARACTER_FOR_VARIABLE(c) \
( VALID_FIRST_CHARACTER_FOR_VARIABLE(c) \
|| ((c) >= '0' && (c) <= '9'))
/* Append the char argument to the result string, automatically resizing it
if needed. */
#define EMIT_CHAR(c) \
do \
{ \
if (out_index == allocated_size) { \
allocated_size *= 2; \
/*fprintf (stderr, "ALLOCATED SIZE: %i -> %i\n", (int) allocated_size / 2, (int) allocated_size);*/\
* out = realloc (* out, allocated_size); \
if (* out == NULL) \
FATAL (PEP_OUT_OF_MEMORY, \
"cannot grow buffer"); \
} \
(* out) [out_index] = (c); \
out_index ++; \
} \
while (false)
/* Append the string argument to the output string, automatically resizing
it as needed. */
#define EMIT_STRING(s) \
do { \
const char *p; \
for (p = (s); (* p) != '\0'; p ++) \
EMIT_CHAR (* p); \
} while (false)
/* Emit the expansion of the environment variable whose name is delimited on
the left by variable_name_beginning and on the right by the character
coming right *before* in. Fail fatally if the variable is unbound.
The expansion is emitted by appending to the result string, automatically
resizing it as needed. */
#define EMIT_CURRENT_VARIABLE \
do { \
const char *variable_past_end = in; \
size_t variable_name_length \
= variable_past_end - variable_name_beginning; \
strcpy (variable_name_copy, variable_name_beginning); \
variable_name_copy [variable_name_length] = '\0'; \
const char *variable_value = getenv (variable_name_copy); \
if (variable_value == NULL) \
FATAL_NAME (PEP_UNBOUND_ENVIRONMENT_VARIABLE, \
"unbound variable", variable_name_copy); \
EMIT_STRING (variable_value); \
} while (false)
#define FATAL(code, message) \
do { res = (code); goto failure; } while (false)
#define FATAL_NAME(code, message, name) \
FATAL((code), (message))
/* We can allocate buffers, now that we have FATAL. */
if ((variable_name_copy
= malloc (in_length + 1 /* a safe upper bound for a sub-string. */))
== NULL)
FATAL (PEP_OUT_OF_MEMORY, "out of mmeory");
if (((* out) = malloc (allocated_size)) == NULL)
FATAL (PEP_OUT_OF_MEMORY, "out of memory");
/* This logic implements a DFA. */
enum _expand_variable_state s = _expand_variable_state_non_variable;
char c;
while (true) {
c = * in;
switch (s) {
case _expand_variable_state_non_variable:
if (c == '$') {
variable_name_beginning = in + 1;
s = _expand_variable_state_after_dollar;
}
else if (c == '\\')
s = _expand_variable_state_after_backslash;
else /* This includes c == '\0'. */
EMIT_CHAR (c);
if (c == '\0')
goto success;
break;
case _expand_variable_state_after_backslash:
if (c == '$' || c == '\\') {
EMIT_CHAR (c);
s = _expand_variable_state_non_variable;
}
else if (c == '\0') /* Just to give a nicer error message */
FATAL (PEP_PATH_SYNTAX_ERROR, "trailing unescaped '\\'");
else /* this would be correct even with '\0' */
FATAL (PEP_PATH_SYNTAX_ERROR, "invalid escape");
break;
case _expand_variable_state_after_dollar:
if (VALID_FIRST_CHARACTER_FOR_VARIABLE (c))
s = _expand_variable_state_in_variable;
else if (c == '\0') /* Just to give a nicer error message */
FATAL (PEP_PATH_SYNTAX_ERROR,"trailing '$' character");
else if (c == '\\') /* Just to give a nicer error message */
FATAL (PEP_PATH_SYNTAX_ERROR,
"empty variable name followed by escape");
else if (c == '$') /* Just to give a nicer error message */
FATAL (PEP_PATH_SYNTAX_ERROR, "two consecutive '$' characters");
else
FATAL (PEP_PATH_SYNTAX_ERROR,
"invalid variable first character after '$'");
break;
case _expand_variable_state_in_variable:
if (VALID_NON_FIRST_CHARACTER_FOR_VARIABLE (c))
/* Do nothing */;
else if (c == '\\') {
EMIT_CURRENT_VARIABLE;
s = _expand_variable_state_after_backslash;
}
else {
/* This includes c == '\0'. */
EMIT_CURRENT_VARIABLE;
EMIT_CHAR (c);
if (c == '\0')
goto success;
else
s = _expand_variable_state_non_variable;
}
break;
default:
FATAL (PEP_STATEMACHINE_INVALID_STATE /* Slightly questionable: this
should be an assertion. */,
"impossible DFA state");
} /* switch */
in ++;
} /* while */
success:
free(variable_name_copy);
return res;
failure:
free(* out);
* out = NULL;
goto success;
#undef VALID_FIRST_CHARACTER_FOR_VARIABLE
#undef VALID_NON_FIRST_CHARACTER_FOR_VARIABLE
#undef EMIT_CHAR
#undef EMIT_STRING
#undef EMIT_CURRENT_VARIABLE
#undef FATAL
#undef FATAL_NAME
}
/*
* Internal path caching functionality
* **********************************************************************
*/
/* Several functions in this compilation unit return paths to files or
* directories, always returning pointers to the same internally managed memory
* at every call.
*
* The cache is filled at engine initialisation, using the value of environment
* variables at initialisation time: after that point no out-of-memory errors
* are possible, until reset.
*
* In debugging mode the cache can be "reset", with every path recomputed on
* demand according to the current environment.
*/
/* For each path we define:
- a static char * variable pointing to the cached value;
- a prototype for a static function returning a malloc-allocated copy of
the value, unexapanded, not using the cache (to be defined below by hand);
- a public API function returning a pointer to cached memory. */
#define DEFINE_CACHED_PATH(name) \
/* A static variable holding the cached path, or NULL. */ \
static char *_ ## name ## _cache = NULL; \
\
/* A prototype for the hand-written function returning the \
computed value for the path, without using the cache and \
without expanding variables. */ \
static char *_ ## name(void); \
\
/* The public version of the function, using the cache. */ \
DYNAMIC_API const char *name(void) \
{ \
if (_ ## name ## _cache == NULL) { \
/* It is unusual and slightly bizarre than a path is \
accessed before initialisation; however it can happen, \
for example in the engine test suite. */ \
fix ENGINE-956 It is now possible to use shell environment variables in PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY, expanded at *run* time. This is meant to allow more freedom to the deployment engineer, without affecting development. Notice that, when PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY are defined in the Makefile, dollar signs must be escaped (a dollar becomes a double dollar) because of *make* syntax: this has nothing to do with pEp engine code. Expansion follows the Unix shell $VARIABLE syntax: ${VARIABLE} is not supported. See _expand_variables. src/platform_unix.c contained some duplicated logic about caching path results into static variables; this change set would have added to the complexity by calling the new path expansion function, in many different places. Seize the occasion for factoring. Do not change the meaning of PER_USER_DIRECTORY yet; I would like to do it, since it is confusing and inconsistent with per_user_directory (PER_USER_DIRECTORY is a relative path on Unix, while per_user_directory is absolute), but the actual semantics with respect to $HOME and $PEP_HOME is complicated and I do not want to break it. New API function per_user_relative_directory. Remove the ugly "reset" argument from unix_local_db (which was conditionally defined according to NDEBUG!), used to force path re-computation in the test suite after changing an environment variable so as to work in a new "home" directory. In the place of this reset argument add clear API functions to the engine for handling the cache. My quick grapping and IRC interaction confirm that nobody was using the functionality out of the engine test suite. Adapt the test suite to use the new API. Tentatively add caching and expansion functionality to android_system_db as well.
2 years ago
reset_path_cache(); \
} \
assert (_ ## name ## _cache != NULL); \
fix ENGINE-956 It is now possible to use shell environment variables in PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY, expanded at *run* time. This is meant to allow more freedom to the deployment engineer, without affecting development. Notice that, when PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY are defined in the Makefile, dollar signs must be escaped (a dollar becomes a double dollar) because of *make* syntax: this has nothing to do with pEp engine code. Expansion follows the Unix shell $VARIABLE syntax: ${VARIABLE} is not supported. See _expand_variables. src/platform_unix.c contained some duplicated logic about caching path results into static variables; this change set would have added to the complexity by calling the new path expansion function, in many different places. Seize the occasion for factoring. Do not change the meaning of PER_USER_DIRECTORY yet; I would like to do it, since it is confusing and inconsistent with per_user_directory (PER_USER_DIRECTORY is a relative path on Unix, while per_user_directory is absolute), but the actual semantics with respect to $HOME and $PEP_HOME is complicated and I do not want to break it. New API function per_user_relative_directory. Remove the ugly "reset" argument from unix_local_db (which was conditionally defined according to NDEBUG!), used to force path re-computation in the test suite after changing an environment variable so as to work in a new "home" directory. In the place of this reset argument add clear API functions to the engine for handling the cache. My quick grapping and IRC interaction confirm that nobody was using the functionality out of the engine test suite. Adapt the test suite to use the new API. Tentatively add caching and expansion functionality to android_system_db as well.
2 years ago
return _ ## name ## _cache; \
}
/* Define cached paths using the functionality above: */
DEFINE_CACHED_PATH (per_user_relative_directory)
DEFINE_CACHED_PATH (per_user_directory)
DEFINE_CACHED_PATH (per_machine_directory)
#ifdef ANDROID
DEFINE_CACHED_PATH (android_system_db)
#endif
DEFINE_CACHED_PATH (unix_system_db)
DEFINE_CACHED_PATH (unix_local_db)
/* Free every cache variable and re-initialise it to NULL: this
re-initialisation is important when this function is used here,
internally, as part of cleanup on errors. */
DYNAMIC_API void clear_path_cache (void)
{
#define UNSET(name) \
do { \
free((void *) _ ## name ## _cache); \
(_ ## name ## _cache) = NULL; \
} while (false)
UNSET (per_user_relative_directory);
UNSET (per_user_directory);
UNSET (per_machine_directory);
#ifdef ANDROID
UNSET (android_system_db);
#endif
UNSET (unix_system_db);
UNSET (unix_local_db);
#undef UNSET
}
DYNAMIC_API PEP_STATUS reset_path_cache(void)
{
PEP_STATUS res = PEP_STATUS_OK;
#define SET_OR_FAIL(name) \
do { \
unexpanded_path = (_ ## name)(); \
if (unexpanded_path == NULL) { \
res = PEP_OUT_OF_MEMORY; \
goto free_everything_and_fail; \
} \
res = _expand_variables(& _ ## name ## _cache, unexpanded_path); \
if (res != PEP_STATUS_OK) \
goto free_everything_and_fail; \
/* Clear unxpanded_path for the next call of SET_OR_FAIL. */ \
free((void *) unexpanded_path); \
unexpanded_path = NULL; \
} while (false)
/* Start by releasing memory, which is needed in case this is not the first
invocation. */
fix ENGINE-956 It is now possible to use shell environment variables in PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY, expanded at *run* time. This is meant to allow more freedom to the deployment engineer, without affecting development. Notice that, when PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY are defined in the Makefile, dollar signs must be escaped (a dollar becomes a double dollar) because of *make* syntax: this has nothing to do with pEp engine code. Expansion follows the Unix shell $VARIABLE syntax: ${VARIABLE} is not supported. See _expand_variables. src/platform_unix.c contained some duplicated logic about caching path results into static variables; this change set would have added to the complexity by calling the new path expansion function, in many different places. Seize the occasion for factoring. Do not change the meaning of PER_USER_DIRECTORY yet; I would like to do it, since it is confusing and inconsistent with per_user_directory (PER_USER_DIRECTORY is a relative path on Unix, while per_user_directory is absolute), but the actual semantics with respect to $HOME and $PEP_HOME is complicated and I do not want to break it. New API function per_user_relative_directory. Remove the ugly "reset" argument from unix_local_db (which was conditionally defined according to NDEBUG!), used to force path re-computation in the test suite after changing an environment variable so as to work in a new "home" directory. In the place of this reset argument add clear API functions to the engine for handling the cache. My quick grapping and IRC interaction confirm that nobody was using the functionality out of the engine test suite. Adapt the test suite to use the new API. Tentatively add caching and expansion functionality to android_system_db as well.
2 years ago
clear_path_cache ();
const char *unexpanded_path = NULL;
SET_OR_FAIL (per_user_relative_directory);
SET_OR_FAIL (per_user_directory);
SET_OR_FAIL (per_machine_directory);
#ifdef ANDROID
SET_OR_FAIL (android_system_db);
#endif
SET_OR_FAIL (unix_system_db);
SET_OR_FAIL (unix_local_db);
return res;
free_everything_and_fail:
free((void *) unexpanded_path);
clear_path_cache ();
return res;
#undef SET_OR_FAIL
}
/**
* @internal
*
* <!-- _per_user_directory() -->
*
* @brief TODO
*
*/
static char *_per_user_relative_directory(void)
{
return _strdup_or_NULL(PER_USER_DIRECTORY);
}
/**
* @internal
*
* <!-- _per_user_directory() -->
*
* @brief TODO
*
*/
fix ENGINE-956 It is now possible to use shell environment variables in PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY, expanded at *run* time. This is meant to allow more freedom to the deployment engineer, without affecting development. Notice that, when PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY are defined in the Makefile, dollar signs must be escaped (a dollar becomes a double dollar) because of *make* syntax: this has nothing to do with pEp engine code. Expansion follows the Unix shell $VARIABLE syntax: ${VARIABLE} is not supported. See _expand_variables. src/platform_unix.c contained some duplicated logic about caching path results into static variables; this change set would have added to the complexity by calling the new path expansion function, in many different places. Seize the occasion for factoring. Do not change the meaning of PER_USER_DIRECTORY yet; I would like to do it, since it is confusing and inconsistent with per_user_directory (PER_USER_DIRECTORY is a relative path on Unix, while per_user_directory is absolute), but the actual semantics with respect to $HOME and $PEP_HOME is complicated and I do not want to break it. New API function per_user_relative_directory. Remove the ugly "reset" argument from unix_local_db (which was conditionally defined according to NDEBUG!), used to force path re-computation in the test suite after changing an environment variable so as to work in a new "home" directory. In the place of this reset argument add clear API functions to the engine for handling the cache. My quick grapping and IRC interaction confirm that nobody was using the functionality out of the engine test suite. Adapt the test suite to use the new API. Tentatively add caching and expansion functionality to android_system_db as well.
2 years ago
static char *_per_user_directory(void)
{
fix ENGINE-956 It is now possible to use shell environment variables in PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY, expanded at *run* time. This is meant to allow more freedom to the deployment engineer, without affecting development. Notice that, when PER_USER_DIRECTORY and PER_MACHINE_DIRECTORY are defined in the Makefile, dollar signs must be escaped (a dollar becomes a double dollar) because of *make* syntax: this has nothing to do with pEp engine code. Expansion follows the Unix shell $VARIABLE syntax: ${VARIABLE} is not supported. See _expand_variables. src/platform_unix.c contained some duplicated logic about caching path results into static variables; this change set would have added to the complexity by calling the new path expansion function, in many different places. Seize the occasion for factoring. Do not change the meaning of PER_USER_DIRECTORY yet; I would like to do it, since it is confusing and inconsistent with per_user_directory (PER_USER_DIRECTORY is a relative path on Unix, while per_user_directory is absolute), but the actual semantics with respect to $HOME and $PEP_HOME is complicated and I do not want to break it. New API function per_user_relative_directory. Remove the ugly "reset" argument from unix_local_db (which was conditionally defined according to NDEBUG!), used to force path re-computation in the test suite after changing an environment variable so as to work in a new "home" directory. In the place of this reset argument add clear API functions to the engine for handling the cache. My quick grapping and IRC interaction confirm that nobody was using the functionality out of the engine test suite. Adapt the test suite to use the new API. Tentatively add caching and expansion functionality to android_system_db as well.
2 years ago
char *path = NULL;