From 8aa4e4ff1e814a92efd1d1e9a06c7490c29aba33 Mon Sep 17 00:00:00 2001
From: Bananymous <oskari.alaranta@bananymous.com>
Date: Wed, 21 May 2025 18:11:22 +0300
Subject: [PATCH] LibC: Implement `clearenv`

This is GNU extension but seems nice to have :D
---
 userspace/libraries/LibC/environ.cpp      | 32 +++++++++++++++++++++--
 userspace/libraries/LibC/include/stdlib.h |  1 +
 2 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/userspace/libraries/LibC/environ.cpp b/userspace/libraries/LibC/environ.cpp
index 2769f9d0..781c379b 100644
--- a/userspace/libraries/LibC/environ.cpp
+++ b/userspace/libraries/LibC/environ.cpp
@@ -19,7 +19,7 @@ static int malloc_environ()
 	ASSERT(!s_environ_malloced);
 
 	size_t environ_count = 0;
-	while (environ[environ_count])
+	while (environ && environ[environ_count])
 		environ_count++;
 
 	const size_t bitmap_size = (environ_count + 7) / 8;
@@ -111,12 +111,37 @@ static int putenv_impl(char* string, bool malloced)
 	return 0;
 }
 
+int clearenv(void)
+{
+	if (s_environ_malloced)
+	{
+		ASSERT(environ);
+
+		for (size_t i = 0; environ[i]; i++)
+		{
+			const size_t byte = i / 8;
+			const size_t mask = 1 << (i % 8);
+			if (s_environ_bitmap[byte] & mask)
+				free(environ[i]);
+		}
+
+		free(s_environ_bitmap);
+		free(environ);
+	}
+
+	environ = nullptr;
+	s_environ_count = 0;
+	s_environ_bitmap = nullptr;
+	s_environ_malloced = false;
+	return 0;
+}
+
 char* getenv(const char* name)
 {
 	if (environ == nullptr)
 		return nullptr;
 	const size_t namelen = strlen(name);
-	for (int i = 0; environ[i]; i++)
+	for (size_t i = 0; environ[i]; i++)
 		if (strncmp(name, environ[i], namelen) == 0)
 			if (environ[i][namelen] == '=')
 				return environ[i] + namelen + 1;
@@ -154,6 +179,9 @@ int unsetenv(const char* name)
 		return -1;
 	}
 
+	if (environ == nullptr)
+		return 0;
+
 	const size_t namelen = strlen(name);
 
 	size_t i = 0;
diff --git a/userspace/libraries/LibC/include/stdlib.h b/userspace/libraries/LibC/include/stdlib.h
index 63449d2b..b93cba78 100644
--- a/userspace/libraries/LibC/include/stdlib.h
+++ b/userspace/libraries/LibC/include/stdlib.h
@@ -51,6 +51,7 @@ long				atol(const char* str);
 long long			atoll(const char* str);
 void*				bsearch(const void* key, const void* base, size_t nel, size_t width, int (*compar)(const void*, const void*));
 void*				calloc(size_t nelem, size_t elsize);
+int					clearenv(void);
 div_t				div(int numer, int denom);
 double				drand48(void);
 double				erand48(unsigned short xsubi[3]);