mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 10:48:11 +00:00
LibC: Add setenv().
If I'm understanding the standard C library correctly, setenv() copies while putenv() does not. That's really confusing and putenv() basically sucks. To know which environment variables to free on replacement and which ones to leave alone, we keep track of the ones malloced by setenv in a side table. This patch also moves Shell to using setenv() instead of putenv(). Fixes #29.
This commit is contained in:
parent
d31ce9eccd
commit
96db775ac1
3 changed files with 27 additions and 10 deletions
|
@ -46,6 +46,16 @@ void abort()
|
|||
raise(SIGABRT);
|
||||
}
|
||||
|
||||
static HashTable<char*> s_malloced_environment_variables;
|
||||
|
||||
static void free_environment_variable_if_needed(const char* var)
|
||||
{
|
||||
if (!s_malloced_environment_variables.contains((char*)var))
|
||||
return;
|
||||
free((void*)var);
|
||||
s_malloced_environment_variables.remove((char*)var);
|
||||
}
|
||||
|
||||
char* getenv(const char* name)
|
||||
{
|
||||
size_t vl = strlen(name);
|
||||
|
@ -89,9 +99,22 @@ int unsetenv(const char* name)
|
|||
// Shuffle the existing array down by one.
|
||||
memmove(&environ[skip], &environ[skip+1], ((environ_size-1)-skip) * sizeof(environ[0]));
|
||||
environ[environ_size-1] = nullptr;
|
||||
|
||||
free_environment_variable_if_needed(name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int setenv(const char* name, const char* value, int overwrite)
|
||||
{
|
||||
if (!overwrite && !getenv(name))
|
||||
return 0;
|
||||
auto length = strlen(name) + strlen(value) + 2;
|
||||
auto* var = (char*)malloc(length);
|
||||
snprintf(var, length, "%s=%s", name, value);
|
||||
s_malloced_environment_variables.set(var);
|
||||
return putenv(var);
|
||||
}
|
||||
|
||||
int putenv(char* new_var)
|
||||
{
|
||||
char* new_eq = strchr(new_var, '=');
|
||||
|
@ -111,6 +134,7 @@ int putenv(char* new_var)
|
|||
continue; // can't match
|
||||
|
||||
if (strncmp(new_var, old_var, new_var_len) == 0) {
|
||||
free_environment_variable_if_needed(old_var);
|
||||
environ[environ_size] = new_var;
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue