forked from Bananymous/banan-os
LibC: implement setenv, unsetenv, putenv
This commit is contained in:
parent
064ce568c2
commit
86f58f60cb
|
@ -57,6 +57,8 @@ namespace Kernel
|
|||
int block_until_exit();
|
||||
BAN::ErrorOr<pid_t> wait(pid_t pid, int* stat_loc, int options);
|
||||
|
||||
BAN::ErrorOr<void> setenvp(char** envp);
|
||||
|
||||
BAN::ErrorOr<int> open(BAN::StringView, int);
|
||||
BAN::ErrorOr<void> close(int fd);
|
||||
BAN::ErrorOr<size_t> read(int fd, void* buffer, size_t count);
|
||||
|
|
|
@ -389,6 +389,13 @@ namespace Kernel
|
|||
return ret;
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::setenvp(char** envp)
|
||||
{
|
||||
LockGuard _(m_lock);
|
||||
m_userspace_info.envp = envp;
|
||||
return {};
|
||||
}
|
||||
|
||||
void Process::load_elf(LibELF::ELF& elf)
|
||||
{
|
||||
ASSERT(elf.is_native());
|
||||
|
|
|
@ -136,6 +136,14 @@ namespace Kernel
|
|||
return 0;
|
||||
}
|
||||
|
||||
long sys_setenvp(char** envp)
|
||||
{
|
||||
auto ret = Process::current().setenvp(envp);
|
||||
if (ret.is_error())
|
||||
return -ret.error().get_error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" long sys_fork_trampoline();
|
||||
|
||||
extern "C" long cpp_syscall_handler(int syscall, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5)
|
||||
|
@ -204,6 +212,9 @@ namespace Kernel
|
|||
case SYS_STAT:
|
||||
ret = sys_stat((const char*)arg1, (struct stat*)arg2, (int)arg3);
|
||||
break;
|
||||
case SYS_SETENVP:
|
||||
ret = sys_setenvp((char**)arg1);
|
||||
break;
|
||||
default:
|
||||
Kernel::panic("Unknown syscall {}", syscall);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ __BEGIN_DECLS
|
|||
#define SYS_REALLOC 16
|
||||
#define SYS_WAIT 17
|
||||
#define SYS_STAT 18
|
||||
#define SYS_SETENVP 19
|
||||
|
||||
__END_DECLS
|
||||
|
||||
|
|
112
libc/stdlib.cpp
112
libc/stdlib.cpp
|
@ -7,6 +7,8 @@
|
|||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
extern "C" char** environ;
|
||||
|
||||
extern "C" void _fini();
|
||||
|
||||
void abort(void)
|
||||
|
@ -54,9 +56,117 @@ int atoi(const char* str)
|
|||
return negative ? -res : res;
|
||||
}
|
||||
|
||||
char* getenv(const char*)
|
||||
char* getenv(const char* name)
|
||||
{
|
||||
if (environ == nullptr)
|
||||
return nullptr;
|
||||
size_t len = strlen(name);
|
||||
for (int i = 0; environ[i]; i++)
|
||||
if (strncmp(name, environ[i], len) == 0)
|
||||
if (environ[i][len] == '=')
|
||||
return environ[i] + len + 1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int setenv(const char* name, const char* val, int overwrite)
|
||||
{
|
||||
if (name == nullptr || !name[0] || strchr(name, '='))
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!overwrite && getenv(name))
|
||||
return 0;
|
||||
|
||||
size_t namelen = strlen(name);
|
||||
size_t vallen = strlen(val);
|
||||
|
||||
char* string = (char*)malloc(namelen + vallen + 2);
|
||||
memcpy(string, name, namelen);
|
||||
string[namelen] = '=';
|
||||
memcpy(string + namelen + 1, val, vallen);
|
||||
string[namelen + vallen + 1] = '\0';
|
||||
|
||||
return putenv(string);
|
||||
}
|
||||
|
||||
int unsetenv(const char* name)
|
||||
{
|
||||
if (name == nullptr || !name[0] || strchr(name, '='))
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t len = strlen(name);
|
||||
|
||||
bool found = false;
|
||||
for (int i = 0; environ[i]; i++)
|
||||
{
|
||||
if (!found && strncmp(environ[i], name, len) == 0 && environ[i][len] == '=')
|
||||
{
|
||||
free(environ[i]);
|
||||
found = true;
|
||||
}
|
||||
if (found)
|
||||
environ[i] = environ[i + 1];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int putenv(char* string)
|
||||
{
|
||||
if (string == nullptr || !string[0])
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cnt = 0;
|
||||
for (int i = 0; string[i]; i++)
|
||||
if (string[i] == '=')
|
||||
cnt++;
|
||||
if (cnt != 1)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int namelen = strchr(string, '=') - string;
|
||||
for (int i = 0; environ[i]; i++)
|
||||
{
|
||||
if (strncmp(environ[i], string, namelen + 1) == 0)
|
||||
{
|
||||
free(environ[i]);
|
||||
environ[i] = string;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int env_count = 0;
|
||||
while (environ[env_count])
|
||||
env_count++;
|
||||
|
||||
char** new_envp = (char**)malloc(sizeof(char*) * (env_count + 2));
|
||||
if (new_envp == nullptr)
|
||||
{
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < env_count; i++)
|
||||
new_envp[i] = environ[i];
|
||||
new_envp[env_count] = string;
|
||||
new_envp[env_count + 1] = nullptr;
|
||||
|
||||
free(environ);
|
||||
environ = new_envp;
|
||||
|
||||
if (syscall(SYS_SETENVP, environ) == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* malloc(size_t bytes)
|
||||
|
|
|
@ -157,6 +157,12 @@ long syscall(long syscall, ...)
|
|||
ret = Kernel::syscall(SYS_STAT, (uintptr_t)path, (uintptr_t)buf, flags);
|
||||
break;
|
||||
}
|
||||
case SYS_SETENVP:
|
||||
{
|
||||
char** envp = va_arg(args, char**);
|
||||
ret = Kernel::syscall(SYS_SETENVP, (uintptr_t)envp);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
puts("LibC: Unhandeled syscall");
|
||||
ret = -ENOSYS;
|
||||
|
|
Loading…
Reference in New Issue