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.
This commit is contained in:
Angus Gratton 2019-06-28 13:35:55 +10:00 committed by bot
parent 70474ae844
commit bd69998516
4 changed files with 131 additions and 16 deletions

View file

@ -192,13 +192,13 @@ lxdialog/%.o: $(SRCDIR)/lxdialog/%.c
lxdialog := lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o
lxdialog += lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o
conf-objs := conf.o zconf.tab.o
mconf-objs := mconf.o zconf.tab.o $(lxdialog)
nconf-objs := nconf.o zconf.tab.o nconf.gui.o
kxgettext-objs := kxgettext.o zconf.tab.o
conf-objs := conf.o zconf.tab.o expand_env.o
mconf-objs := mconf.o zconf.tab.o $(lxdialog) expand_env.o
nconf-objs := nconf.o zconf.tab.o nconf.gui.o expand_env.o
kxgettext-objs := kxgettext.o zconf.tab.o expand_env.o
qconf-cxxobjs := qconf.o
qconf-objs := zconf.tab.o
gconf-objs := gconf.o zconf.tab.o
qconf-objs := zconf.tab.o expand_env.o
gconf-objs := gconf.o zconf.tab.o expand_env.o
hostprogs-y := conf-idf nconf mconf-idf kxgettext qconf gconf

View file

@ -0,0 +1,88 @@
#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);
}

View file

@ -0,0 +1,13 @@
#pragma once
/* Expand any $ENV type environment variables in 'input',
return a newly allocated buffer with the result.
Buffer should be freed after use.
This is very basic expansion, doesn't do escaping or anything else.
*/
char *expand_environment(const char *input, const char *src_name, int src_line_no);
/* Free a buffer allocated by expand_environment */
void free_expanded(char *expanded);

View file

@ -13,9 +13,9 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wordexp.h>
#include "lkc.h"
#include "expand_env.h"
#define START_STRSIZE 16
@ -348,19 +348,33 @@ void zconf_nextfile(const char *name)
current_file = file;
}
void zconf_nextfiles(const char *wildcard)
void zconf_nextfiles(const char *expression)
{
wordexp_t p;
char **w;
int i;
/* Expand environment variables in 'expression' */
char* str = expand_environment(expression, zconf_curname(), zconf_lineno());
wordexp(wildcard, &p, 0);
w = p.we_wordv;
/* zconf_nextfile() processes files in LIFO order, so to keep the
files in the order provided we need to process the list backwards
*/
if (str != NULL && strlen(str)) {
char* pos = str + strlen(str); // start at null terminator
for (i = p.we_wordc - 1; i >= 0; i--)
zconf_nextfile(w[i]);
while (pos != str) {
pos--;
if(*pos == ' ') {
*pos = '\0'; // split buffer into multiple c-strings
if (strlen(pos + 1)) {
zconf_nextfile(pos + 1);
}
}
}
wordfree(&p);
if (strlen(str)) { // re-check as first character may have been a space
zconf_nextfile(str);
}
}
free_expanded(str);
}
static void zconf_endfile(void)