OVMS3-idf/tools/kconfig/expand_env.c
Angus Gratton bd69998516 mconf-idf: Use same 'simple expand' logic, same as kconfig-frontends
Previously, wordexp() was used. However for providing Windows builds
of mconf-idf we can't use wordexp() so we use this simplified
environment variable expansion code instead.

The reasoning here is to make the behaviour consistent across Windows
(CMake vs GNU Make), Linux & macOS mconf.
2019-07-01 00:38:55 +00:00

88 lines
2 KiB
C

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include <stdbool.h>
#include "expand_env.h"
static bool allowed_env_var_name(char c)
{
return c != '\0' &&
!isblank(c) &&
!iscntrl(c) &&
c != '/' &&
c != '\\' &&
c != '=' &&
c != '$';
}
#define MAX_LEN (128 * 1024) /* Longest a result can expand to */
/* Very basic expansion that looks for variable references like $NAME and expands them
*
*/
char *expand_environment(const char *input, const char *src_name, int src_line_no)
{
char *result = malloc(MAX_LEN);
char *out = result;
const char *in = input;
while (*in != '\0') {
// check for buffer overflow
if (out >= result + MAX_LEN - 1) {
goto too_long;
}
if (*in != '$') {
// not part of an environment variable name, copy directly
*out++ = *in++;
continue;
}
// *in points to start of an environment variable reference
in++;
const char *env_start = in;
while (allowed_env_var_name(*in)) { // scan to the end of the name
in++;
}
size_t env_len = in - env_start;
// make a buffer to hold the environment variable name
//
// strndup is not available on mingw32, apparently.
char *env_name = calloc(1, env_len + 1);
assert(env_name != NULL);
strncpy(env_name, env_start, env_len);
const char *value = getenv(env_name);
if (value == NULL || strlen(value) == 0) {
printf("%s:%d: undefined environment variable \"%s\"\n",
src_name, src_line_no, env_name);
exit(1);
}
free(env_name);
if (out + strlen(value) >= result + MAX_LEN - 1) {
goto too_long;
}
strcpy(out, value); // append the value to the result (range checked in previous statement)
out += strlen(value);
}
*out = '\0'; // null terminate the result string
return result;
too_long:
printf("%s:%d: Expansion is longer than %d bytes\n",
src_name, src_line_no, MAX_LEN);
free(result);
exit(1);
}
void free_expanded(char *expanded)
{
free(expanded);
}