Skip to content

Commit

Permalink
Merge pull request #105 from AleksArt000/env_rec_fix
Browse files Browse the repository at this point in the history
Simple environment variable parser
  • Loading branch information
ilovethensa authored Aug 9, 2024
2 parents d56b97f + a691fe4 commit 2c5cc1f
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 33 deletions.
3 changes: 2 additions & 1 deletion include/libspm.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ int check_optional_dependencies(char ** dependencies,int dependenciesCount);
int get_repos(char** list);
char** get_all_files(const char* root, const char *path, int *num_files);
int download(char* url, FILE* fp);
int parse_env(char** in);


//end test
Expand Down Expand Up @@ -249,7 +250,7 @@ This function exits the program with the specified status code. If the status co
*/
void quit(int status);

int readConfig(const char* configFilePath);
int readConfig(const char* configFilePath, int overwrite);

// Function to check the existence of package locations
/*
Expand Down
4 changes: 2 additions & 2 deletions src/clean.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ int clean()
// Get the paths to the build and make directories from environment variables
char* build_dir = getenv("SOVIET_BUILD_DIR");
char* make_dir = getenv("SOVIET_MAKE_DIR");
char* cleanups = getenv("SOVIET_CLEANUP");
char* cleanups = strdup(getenv("SOVIET_CLEANUP"));

int result = 0;

char** cleanup_loc;

Check warning on line 24 in src/clean.c

View workflow job for this annotation

GitHub Actions / c-linter

src/clean.c:24:12 [cppcoreguidelines-init-variables]

variable 'cleanup_loc' is not initialized
msg(WARNING, "%s", cleanups);
msg(WARNING, "This will delete: %s", cleanups);
int count = splita(cleanups, ':', &cleanup_loc);

for(int i = 0; i < count; i++)
Expand Down
12 changes: 7 additions & 5 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ ConfigEntry configEntries[] = {
// The number of entries in the configEntries array
const size_t numConfigEntries = sizeof(configEntries) / sizeof(configEntries[0]);

int readConfig(const char* configFilePath)
int readConfig(const char* configFilePath, int overwrite)
{
if (configFilePath == NULL) {
configFilePath = DEFAULT_CONFIG_FILE; // Use the default config file path
Expand Down Expand Up @@ -74,10 +74,11 @@ int readConfig(const char* configFilePath)
}
}

char line[1024];
char* line = calloc(1024, 1);

while (fgets(line, sizeof(line), file)) {
while (fgets(line, 1024, file)) {
line[strlen(line) - 1] = 0;
parse_env(&line);

if((line[0] != '#' || (line[0] != '/' && line[1] != '/')) && strstr(line, "=") != 0)
{
Expand All @@ -93,16 +94,17 @@ int readConfig(const char* configFilePath)
dbg(2, "Key: %s Value: %s", key, value);

// Set environment variables based on the key-value pairs in the config file
setenv(key, value, 0);
setenv(key, value, overwrite);
}
}

free(line);
fclose(file);

// Set environment variables for missing keys with their default values
for (size_t i = 0; i < numConfigEntries; i++) {
if (getenv(configEntries[i].key) == NULL) {
setenv(configEntries[i].key, configEntries[i].default_value, 0);
setenv(configEntries[i].key, configEntries[i].default_value, overwrite);
}
}

Expand Down
85 changes: 85 additions & 0 deletions src/environment.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#include "stdio.h"
#include <stdlib.h>
#include <string.h>

#include "libspm.h"
#include "globals.h"
#include "cutils.h"

#include <stdbool.h>

// This will parse a string for environment variables
// It makes an assumption that a variable is: $A-Z_0-9

int parse_env(char** in)
{
dbg(2, "Parsing string %s for env variables", *in);
char* env = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890_";
char* start = strchr(*in, '$');
char* end = NULL;
int i, start_i;

Check warning on line 20 in src/environment.c

View workflow job for this annotation

GitHub Actions / c-linter

src/environment.c:20:5 [readability-isolate-declaration]

multiple declarations in a single statement reduces readability

Check warning on line 20 in src/environment.c

View workflow job for this annotation

GitHub Actions / c-linter

src/environment.c:20:9 [cppcoreguidelines-init-variables]

variable 'i' is not initialized

Check warning on line 20 in src/environment.c

View workflow job for this annotation

GitHub Actions / c-linter

src/environment.c:20:12 [cppcoreguidelines-init-variables]

variable 'start_i' is not initialized

if (start == NULL)
{
return 0;
}

dbg(2, "Start: %s", start);

start_i = strlen(*in) - strlen(start);

dbg(2, "Start i: %d, from '%d' and '%d'", start_i, strlen(*in), strlen(start));

for (i = 1; i < strlen(start); i++)
{
end = strchr(env, start[i]);

if (end == NULL)
{
if(i == 0)
{
return 0;
}

if(start[i] != '\0')
{
end = &start[i];
}

break;
}

if(i + 1 == strlen(start))
{
end = " ";
}
}

char* var = strdup(*in + start_i + 1);
var[--i] = '\0';
(*in)[start_i] = '\0';

dbg(2, "Var: %s", var);
dbg(2, "In: %s", *in);

char* full_var = getenv(var);

if(full_var == NULL)
{
return 0;
}

dbg(2, "Full var: %s", full_var);

char* full_in = calloc(strlen(*in) + strlen(full_var) + strlen(end) + 1, 1);

Check warning on line 74 in src/environment.c

View workflow job for this annotation

GitHub Actions / c-linter

src/environment.c:74:61 [clang-analyzer-core.NonNullParamChecker]

Null pointer passed to 1st parameter expecting 'nonnull'

sprintf(full_in, "%s%s%s", *in, full_var, end);

Check warning on line 76 in src/environment.c

View workflow job for this annotation

GitHub Actions / c-linter

src/environment.c:76:5 [clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling]

Call to function 'sprintf' is insecure as it does not provide bounding of the memory buffer or security checks introduced in the C11 standard. Replace with analogous functions that support length arguments or provides boundary checks such as 'sprintf_s' in case of C11

free(*in);
free(var);
*in = full_in;

dbg(2, "Result: %s", *in);

return parse_env(in);
}
2 changes: 1 addition & 1 deletion src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ void init() {
setenv("SOVIET_CONFIG_FILE", "/etc/cccp.conf", 0);
setenv("SOVIET_REPOS_LIST", "/etc/sources.list", 0);
dbg(3, "Cleaning...");
readConfig(getenv("SOVIET_CONFIG_FILE"));
readConfig(getenv("SOVIET_CONFIG_FILE"), 0);

dbg(3, "Setting variables");

Expand Down
21 changes: 2 additions & 19 deletions src/install.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,6 @@ int install_package_source(const char* spm_path, int as_dep) {
- -1: Installation failed.
*/
int f_install_package_source(const char* spm_path, int as_dep, char* repo) {

// Read the config in case anything got overwritten in the ecmp file

readConfig(getenv("SOVIET_CONFIG_FILE"));

// Check if spm_path is NULL

if (spm_path == NULL) {
Expand Down Expand Up @@ -89,7 +84,7 @@ int f_install_package_source(const char* spm_path, int as_dep, char* repo) {
char* env_path = calloc(MAX_PATH, 1);
sprintf(env_path, "%s/%s", getenv("SOVIET_ENV_DIR"), pkg.environment);

readConfig(env_path);
readConfig(env_path, 1);
}

// Set global environment variables
Expand Down Expand Up @@ -140,15 +135,7 @@ int f_install_package_source(const char* spm_path, int as_dep, char* repo) {

if (pkg.url != NULL)
{
/* IMPORTANT*/
// This seemingly pointless piece of code is actually very important
// Basically it evaluate the nested variables in the URL
// without it everything crashes
// I dont like calling exec() so its a temporary solution
// I dont know how to fix it without manually parsing eveything, a pain
char cmd[1024];
sprintf(cmd,"echo %s",pkg.url);
pkg.url = exec(cmd);
parse_env(&(pkg.url));
dbg(1, "URL: %s", pkg.url);
setenv("URL", pkg.url, 1);
}
Expand Down Expand Up @@ -309,10 +296,6 @@ __attribute__((unused)) int uncompress_binary(const char* bin_path, const char*
*/
int install_package_binary(const char* archivePath, int as_dep, const char* repo) {

// Read the config in case anything got overwritten in the ecmp file

readConfig(getenv("SOVIET_CONFIG_FILE"));

struct package pkg;

// Get required environment variables
Expand Down
2 changes: 2 additions & 0 deletions src/make.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ int make(char* package_dir, struct package* pkg) {

// This seems stupid, but should work
char* file_name = strtok(pkg->files[i], " ");
parse_env(&file_name);
char* file_url = strtok(NULL, " ");
parse_env(&file_url);
char* file_sha256 = strtok(NULL, " ");

sprintf(location, "%s/%s", getenv("SOVIET_MAKE_DIR"), file_name);
Expand Down
8 changes: 3 additions & 5 deletions test/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ void test_move() {
dbg(2,"creating test files");
// make all files
for (int i = 0; i < l_f_count; i++)
{
{
dbg(3,"Creating %s\n",l_files[i]);
char* path = malloc(256);
sprintf(path,"%s/%s",build_dir,l_files[i]);
Expand Down Expand Up @@ -147,9 +147,7 @@ void test_make(char* spm_path) {
setenv("NAME", p.name, 1);
setenv("VERSION", p.version, 1);
if (p.url != NULL) {
char cmd[1024];
sprintf(cmd,"echo %s",p.url);
p.url = exec(cmd);
parse_env(&(p.url));
dbg(1, "URL: %s", p.url);
setenv("URL", p.url, 1);
}
Expand Down Expand Up @@ -202,7 +200,7 @@ void test_config() {

msg(INFO,"Testing 'readConfig()'..");

assert(readConfig(getenv("SOVIET_CONFIG_FILE")) == 0);
assert(readConfig(getenv("SOVIET_CONFIG_FILE"), 0) == 0);
return;
}

Expand Down

0 comments on commit 2c5cc1f

Please sign in to comment.