Skip to content
Snippets Groups Projects
Verified Commit 07563de2 authored by jD91mZM2's avatar jD91mZM2
Browse files

Implement setenv/unsetenv

parent 232a3311
No related branches found
No related tags found
No related merge requests found
......@@ -258,7 +258,7 @@ pub extern "C" fn gcvt(value: c_double, ndigit: c_int, buf: *mut c_char) -> *mut
unimplemented!();
}
unsafe fn find_env(name: *const c_char) -> Option<(usize, *mut c_char)> {
unsafe fn find_env(search: *const c_char) -> Option<(usize, *mut c_char)> {
for (i, item) in platform::inner_environ.iter().enumerate() {
let mut item = *item;
if item == ptr::null_mut() {
......@@ -269,23 +269,25 @@ unsafe fn find_env(name: *const c_char) -> Option<(usize, *mut c_char)> {
);
break;
}
let mut name = name;
let mut search = search;
loop {
let end_of_name = *name == 0 || *name == b'=' as c_char;
if *item == 0 || *item == b'=' as c_char || end_of_name {
if *item == b'=' as c_char || end_of_name {
let end_of_query = *search == 0 || *search == b'=' as c_char;
assert_ne!(*item, 0, "environ has an item without value");
if *item == b'=' as c_char || end_of_query {
if *item == b'=' as c_char && end_of_query {
// Both keys env here
return Some((i, item.offset(1)));
} else {
break;
}
}
if *item != *name {
if *item != *search {
break;
}
item = item.offset(1);
name = name.offset(1);
search = search.offset(1);
}
}
None
......@@ -513,43 +515,16 @@ pub extern "C" fn ptsname(fildes: c_int) -> *mut c_char {
}
#[no_mangle]
pub unsafe extern "C" fn putenv(s: *mut c_char) -> c_int {
let mut s_len = 0;
while *s.offset(s_len) != 0 {
s_len += 1;
}
let ptr;
if let Some((i, _)) = find_env(s) {
let mut item = platform::inner_environ[i];
let mut item_len = 0;
while *item.offset(item_len) != 0 {
item_len += 1;
}
if item_len > s_len {
ptr = item;
} else {
platform::free(item as *mut c_void);
ptr = platform::alloc(s_len as usize + 1) as *mut c_char;
platform::inner_environ[i] = ptr;
}
pub unsafe extern "C" fn putenv(insert: *mut c_char) -> c_int {
assert_ne!(insert, ptr::null_mut(), "putenv(NULL)");
if let Some((i, _)) = find_env(insert) {
platform::free(platform::inner_environ[i] as *mut c_void);
platform::inner_environ[i] = insert;
} else {
ptr = platform::alloc(s_len as usize + 1) as *mut c_char;
let i = platform::inner_environ.len() - 1;
assert_eq!(
platform::inner_environ[i],
ptr::null_mut(),
"last element in environ vector was not null"
);
platform::inner_environ[i] = ptr;
assert_eq!(platform::inner_environ[i], ptr::null_mut(), "environ did not end with null");
platform::inner_environ[i] = insert;
platform::inner_environ.push(ptr::null_mut());
platform::environ = platform::inner_environ.as_mut_ptr();
}
for i in 0..=s_len {
*ptr.offset(i) = *s.offset(i);
}
0
}
......@@ -609,6 +584,64 @@ pub extern "C" fn seed48(seed16v: [c_ushort; 3]) -> c_ushort {
unimplemented!();
}
#[no_mangle]
pub unsafe extern "C" fn setenv(mut key: *const c_char, mut value: *const c_char, overwrite: c_int) -> c_int {
let mut key_len = 0;
while *key.offset(key_len) != 0 {
key_len += 1;
}
let mut value_len = 0;
while *value.offset(value_len) != 0 {
value_len += 1;
}
let index = if let Some((i, existing)) = find_env(key) {
if overwrite == 0 {
return 0;
}
let mut existing_len = 0;
while *existing.offset(existing_len) != 0 {
existing_len += 1;
}
if existing_len >= value_len {
// Reuse existing element's allocation
for i in 0..=value_len {
*existing.offset(i) = *value.offset(i);
}
return 0;
} else {
i
}
} else {
let i = platform::inner_environ.len() - 1;
assert_eq!(platform::inner_environ[i], ptr::null_mut(), "environ did not end with null");
platform::inner_environ.push(ptr::null_mut());
i
};
//platform::free(platform::inner_environ[index] as *mut c_void);
let mut ptr = platform::alloc(key_len as usize + 1 + value_len as usize) as *mut c_char;
platform::inner_environ[index] = ptr;
while *key != 0 {
*ptr = *key;
ptr = ptr.offset(1);
key = key.offset(1);
}
*ptr = b'=' as c_char;
ptr = ptr.offset(1);
while *value != 0 {
*ptr = *value;
ptr = ptr.offset(1);
value = value.offset(1);
}
*ptr = 0;
0
}
// #[no_mangle]
pub extern "C" fn setkey(key: *const c_char) {
unimplemented!();
......@@ -987,6 +1020,16 @@ pub extern "C" fn unlockpt(fildes: c_int) -> c_int {
unimplemented!();
}
#[no_mangle]
pub unsafe extern "C" fn unsetenv(key: *mut c_char) -> c_int {
if let Some((i, _)) = find_env(key) {
// No need to worry about updating the pointer, this does not
// reallocate in any way. And the final null is already shifted back.
platform::inner_environ.remove(i);
}
0
}
#[no_mangle]
pub unsafe extern "C" fn valloc(size: size_t) -> *mut c_void {
memalign(4096, size)
......
It's working!!
Updates accordingly.
in place
TEST=in place
Value overwritten and not in place because it's really long
TEST=in place
Value overwritten and not in place because it's really long
Value deleted successfully!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
//puts(getenv("SHELL"));
//puts(getenv("CC"));
putenv("TEST=It's working!!");
char* owned = malloc(26); // "TEST=Updates accordingly." + NUL
strcpy(owned, "TEST=It's working!!");
putenv(owned);
puts(getenv("TEST"));
strcpy(owned, "TEST=Updates accordingly.");
puts(getenv("TEST"));
// Allocation is reused
setenv("TEST", "in place", 1);
puts(getenv("TEST"));
puts(owned);
// Allocation is not reused
setenv("TEST", "Value overwritten and not in place because it's really long", 1);
puts(getenv("TEST"));
puts(owned);
// Value is not overwritten
setenv("TEST", "Value not overwritten", 0);
puts(getenv("TEST"));
unsetenv("TEST");
char* env = getenv("TEST");
if (env) {
puts("This should be null, but isn't");
puts(env);
return 1;
} else {
puts("Value deleted successfully!");
}
free(owned);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment