|
@@ -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)
|