1use core::{convert::TryFrom, intrinsics, iter, mem, ptr, slice};
6use rand::{
7 RngExt, SeedableRng,
8 distr::{Alphanumeric, Distribution, Uniform},
9};
10use rand_jitter::JitterRng;
11use rand_xorshift::XorShiftRng;
12
13use crate::{
14 byte_literal::ByteLiteral,
15 c_str::CStr,
16 error::{Errno, ResultExt},
17 fs::File,
18 header::{
19 ctype,
20 errno::{self, *},
21 fcntl::*,
22 limits,
23 stdio::flush_io_streams,
24 stdlib::sort::{QsortContext, QsortRContext},
25 string::*,
26 sys_ioctl::*,
27 time::constants::CLOCK_MONOTONIC,
28 unistd::{self, _SC_PAGESIZE, sysconf},
29 wchar::*,
30 },
31 ld_so,
32 out::Out,
33 platform::{
34 self, Pal, Sys,
35 types::{
36 c_char, c_double, c_float, c_int, c_long, c_longlong, c_uint, c_ulong, c_ulonglong,
37 c_ushort, c_void, size_t, ssize_t, uintptr_t, wchar_t,
38 },
39 },
40 raw_cell::RawCell,
41 sync::Once,
42};
43
44mod rand48;
45mod random;
46mod sort;
47
48pub const EXIT_FAILURE: c_int = 1;
50pub const EXIT_SUCCESS: c_int = 0;
52pub const RAND_MAX: c_int = 2_147_483_647;
54
55pub const MB_CUR_MAX: c_int = 4;
58pub const MB_LEN_MAX: c_int = 4;
61
62static ATEXIT_FUNCS: RawCell<[Option<extern "C" fn()>; 32]> = RawCell::new([None; 32]);
63static AT_QUICK_EXIT_FUNCS: RawCell<[Option<extern "C" fn()>; 32]> = RawCell::new([None; 32]);
64static L64A_BUFFER: RawCell<[c_char; 7]> = RawCell::new([0; 7]); static mut RNG: Option<XorShiftRng> = None;
66
67static RNG_SAMPLER: Once<Uniform<c_int>> = Once::new();
69
70fn rng_sampler() -> &'static Uniform<c_int> {
71 RNG_SAMPLER.call_once(|| Uniform::new_inclusive(0, RAND_MAX).expect("within bounds"))
72}
73
74#[unsafe(no_mangle)]
76pub extern "C" fn _Exit(status: c_int) -> ! {
77 unistd::_exit(status);
78}
79
80#[unsafe(no_mangle)]
82pub unsafe extern "C" fn a64l(s: *const c_char) -> c_long {
83 if s.is_null() {
85 return 0;
86 }
87
88 let mut l: i32 = 0;
90
91 for i in 0..6 {
93 let digit_char = unsafe { *s.offset(i) };
94
95 let digit_value = match digit_char {
96 0 => break, 46..=57 => {
98 digit_char - 46
100 }
101 65..=90 => {
102 digit_char - 53
104 }
105 97..=122 => {
106 digit_char - 59
108 }
109 _ => return 0, };
111
112 l |= i32::from(digit_value) << (6 * i);
113 }
114
115 c_long::from(l)
116}
117
118#[unsafe(no_mangle)]
120pub unsafe extern "C" fn abort() -> ! {
121 log::error!("Abort");
122 intrinsics::abort();
123}
124
125#[cfg(not(target_pointer_width = "64"))]
126#[unsafe(no_mangle)]
127static __stack_chk_guard: uintptr_t = 0x19fcadfe;
128
129#[cfg(target_pointer_width = "64")]
130#[unsafe(no_mangle)]
131static __stack_chk_guard: uintptr_t = 0xd048c37519fcadfe;
132
133#[unsafe(no_mangle)]
134unsafe extern "C" fn __stack_chk_fail() -> ! {
135 unsafe { abort() };
136}
137
138#[unsafe(no_mangle)]
140pub extern "C" fn abs(i: c_int) -> c_int {
141 i.abs()
142}
143
144#[unsafe(no_mangle)]
146pub unsafe extern "C" fn aligned_alloc(alignment: size_t, size: size_t) -> *mut c_void {
147 if alignment == 0 || !size.is_multiple_of(alignment) {
148 platform::ERRNO.set(EINVAL);
149 return ptr::null_mut();
150 }
151 #[allow(deprecated)]
154 unsafe {
155 memalign(alignment, size)
156 }
157}
158
159#[unsafe(no_mangle)]
161pub unsafe extern "C" fn at_quick_exit(func: Option<extern "C" fn()>) -> c_int {
162 for i in 0..unsafe { AT_QUICK_EXIT_FUNCS.unsafe_ref().len() } {
163 if unsafe { AT_QUICK_EXIT_FUNCS.unsafe_ref() }[i].is_none() {
164 (unsafe { AT_QUICK_EXIT_FUNCS.unsafe_mut() })[i] = func;
165 return 0;
166 }
167 }
168
169 1
170}
171
172#[unsafe(no_mangle)]
174pub unsafe extern "C" fn atexit(func: Option<extern "C" fn()>) -> c_int {
175 for i in 0..unsafe { ATEXIT_FUNCS.unsafe_ref().len() } {
176 if unsafe { ATEXIT_FUNCS.unsafe_ref() }[i].is_none() {
177 (unsafe { ATEXIT_FUNCS.unsafe_mut() })[i] = func;
178 return 0;
179 }
180 }
181
182 1
183}
184
185#[unsafe(no_mangle)]
187pub unsafe extern "C" fn atof(s: *const c_char) -> c_double {
188 unsafe { strtod(s, ptr::null_mut()) }
189}
190
191macro_rules! dec_num_from_ascii {
192 ($s:expr, $t:ty) => {{
193 let mut s = $s;
194 while ctype::isspace(c_int::from(unsafe { *s })) != 0 {
196 s = unsafe { s.offset(1) };
197 }
198
199 let neg_sign = match unsafe { *s } {
201 0x2d => {
202 s = unsafe { s.offset(1) };
203 true
204 }
205 0x2b => {
207 s = unsafe { s.offset(1) };
208 false
209 }
210 _ => false,
211 };
212
213 let mut n: $t = 0;
214 while ctype::isdigit(c_int::from(unsafe { *s })) != 0 {
215 n = 10 * n - (unsafe { *s } as $t - 0x30);
216 s = unsafe { s.offset(1) };
217 }
218
219 if neg_sign { n } else { -n }
220 }};
221}
222
223#[unsafe(no_mangle)]
225pub unsafe extern "C" fn atoi(s: *const c_char) -> c_int {
226 dec_num_from_ascii!(s, c_int)
227}
228
229#[unsafe(no_mangle)]
231pub unsafe extern "C" fn atol(s: *const c_char) -> c_long {
232 dec_num_from_ascii!(s, c_long)
233}
234
235#[unsafe(no_mangle)]
237pub unsafe extern "C" fn atoll(s: *const c_char) -> c_longlong {
238 dec_num_from_ascii!(s, c_longlong)
239}
240
241unsafe extern "C" fn void_cmp(a: *const c_void, b: *const c_void) -> c_int {
242 (unsafe { *(a.cast::<i32>()) }) - unsafe { *(b.cast::<i32>()) } as c_int
243}
244
245#[unsafe(no_mangle)]
247pub unsafe extern "C" fn bsearch(
248 key: *const c_void,
249 base: *const c_void,
250 nel: size_t,
251 width: size_t,
252 compar: Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>,
253) -> *mut c_void {
254 let mut start = base;
255 let mut len = nel;
256 let cmp_fn = compar.unwrap_or(void_cmp);
257 while len > 0 {
258 let med = (start as size_t + (len >> 1) * width) as *const c_void;
259 let diff = unsafe { cmp_fn(key, med) };
260 if diff == 0 {
261 return med.cast_mut();
262 } else if diff > 0 {
263 start = (med as usize + width) as *const c_void;
264 len -= 1;
265 }
266 len >>= 1;
267 }
268 ptr::null_mut()
269}
270
271#[unsafe(no_mangle)]
273pub unsafe extern "C" fn calloc(nelem: size_t, elsize: size_t) -> *mut c_void {
274 match nelem.checked_mul(elsize) {
276 Some(size) => {
277 let ptr = unsafe { malloc(size) };
280 if !ptr.is_null() {
281 unsafe { ptr.write_bytes(0, size) };
282 }
283 ptr
284 }
285 None => {
286 platform::ERRNO.set(ENOMEM);
288 ptr::null_mut()
289 }
290 }
291}
292
293#[repr(C)]
295pub struct div_t {
296 quot: c_int,
297 rem: c_int,
298}
299
300#[unsafe(no_mangle)]
302pub extern "C" fn div(numer: c_int, denom: c_int) -> div_t {
303 div_t {
304 quot: numer / denom,
305 rem: numer % denom,
306 }
307}
308
309#[unsafe(no_mangle)]
315pub extern "C" fn drand48() -> c_double {
316 let params = rand48::params();
317 let mut xsubi = rand48::xsubi_lock();
318 *xsubi = params.step(*xsubi);
319 xsubi.get_f64()
320}
321
322#[deprecated]
328pub extern "C" fn ecvt(
330 value: c_double,
331 ndigit: c_int,
332 decpt: *mut c_int,
333 sign: *mut c_int,
334) -> *mut c_char {
335 unimplemented!();
336}
337
338#[unsafe(no_mangle)]
348pub unsafe extern "C" fn erand48(xsubi: *mut c_ushort) -> c_double {
349 let params = rand48::params();
350 let xsubi_mut: &mut [c_ushort; 3] =
351 unsafe { slice::from_raw_parts_mut(xsubi, 3).try_into().unwrap() };
352 let new_xsubi_value = params.step(xsubi_mut.into());
353 *xsubi_mut = new_xsubi_value.into();
354 new_xsubi_value.get_f64()
355}
356
357#[unsafe(no_mangle)]
359pub unsafe extern "C" fn exit(status: c_int) -> ! {
360 unsafe extern "C" {
361 static __fini_array_start: extern "C" fn();
362 static __fini_array_end: extern "C" fn();
363 }
364
365 for i in (0..unsafe { ATEXIT_FUNCS.unsafe_ref().len() }).rev() {
366 if let Some(func) = unsafe { ATEXIT_FUNCS.unsafe_ref() }[i] {
367 (func)();
368 }
369 }
370
371 let mut f = core::ptr::from_ref(unsafe { &__fini_array_end });
373 #[allow(clippy::op_ref)]
374 while f > &raw const __fini_array_start {
375 f = unsafe { f.offset(-1) };
376 (unsafe { *f })();
377 }
378
379 unsafe { ld_so::fini() };
380
381 unsafe { crate::pthread::terminate_from_main_thread() };
382
383 unsafe { flush_io_streams() };
384
385 Sys::exit(status);
386}
387
388#[deprecated]
394pub extern "C" fn fcvt(
396 value: c_double,
397 ndigit: c_int,
398 decpt: *mut c_int,
399 sign: *mut c_int,
400) -> *mut c_char {
401 unimplemented!();
402}
403
404#[unsafe(no_mangle)]
406pub unsafe extern "C" fn free(ptr: *mut c_void) {
407 unsafe { platform::free(ptr) };
408}
409
410#[deprecated]
416pub extern "C" fn gcvt(value: c_double, ndigit: c_int, buf: *mut c_char) -> *mut c_char {
418 unimplemented!();
419}
420
421unsafe fn find_env(search: *const c_char) -> Option<(usize, *mut c_char)> {
422 for (i, mut item) in platform::environ_iter().enumerate() {
423 let mut search = search;
424 loop {
425 let end_of_query =
426 unsafe { *search } == 0 || unsafe { *search } == ByteLiteral::cast_cchar(b'=');
427 if unsafe { *item } == 0 {
428 break;
430 }
431 if unsafe { *item } == ByteLiteral::cast_cchar(b'=') || end_of_query {
432 if unsafe { *item } == ByteLiteral::cast_cchar(b'=') && end_of_query {
433 return Some((i, unsafe { item.add(1) }));
435 } else {
436 break;
437 }
438 }
439
440 if unsafe { *item } != unsafe { *search } {
441 break;
442 }
443
444 item = unsafe { item.add(1) };
445 search = unsafe { search.add(1) };
446 }
447 }
448
449 None
450}
451
452#[unsafe(no_mangle)]
454pub unsafe extern "C" fn getenv(name: *const c_char) -> *mut c_char {
455 unsafe { find_env(name) }
456 .map(|val| val.1)
457 .unwrap_or(ptr::null_mut())
458}
459
460#[unsafe(no_mangle)]
462pub unsafe extern "C" fn getsubopt(
463 optionp: *mut *mut c_char,
464 keylistp: *const *mut c_char,
465 valuep: *mut *mut c_char,
466) -> c_int {
467 if optionp.is_null()
468 || (unsafe { *optionp }).is_null()
469 || keylistp.is_null()
470 || valuep.is_null()
471 {
472 return -1;
473 }
474
475 let start = unsafe { *optionp };
476 let mut cursor = start;
477 let mut found_comma = false;
478
479 while unsafe { *cursor } != 0 {
480 if unsafe { *cursor } == ByteLiteral::cast_cchar(b',') {
481 unsafe { *cursor = 0 };
482 unsafe { *optionp = cursor.add(1) };
483 found_comma = true;
484 break;
485 }
486 cursor = unsafe { cursor.add(1) };
487 }
488
489 if !found_comma {
490 unsafe { *optionp = cursor };
491 }
492
493 let mut i = 0;
494 while !(unsafe { *keylistp.add(i) }).is_null() {
495 let token = unsafe { *keylistp.add(i) };
496 let token_len = unsafe { strlen(token) };
497
498 if unsafe { strncmp(start, token, token_len) } == 0 {
499 let suffix_char = unsafe { *start.add(token_len) };
500
501 if suffix_char == ByteLiteral::cast_cchar(b'=') {
502 unsafe { *valuep = start.add(token_len + 1) };
503 return i as c_int;
504 } else if suffix_char == 0 {
505 unsafe { *valuep = ptr::null_mut() };
506 return i as c_int;
507 }
508 }
509 i += 1;
510 }
511
512 unsafe { *valuep = start };
513 -1
514}
515
516#[unsafe(no_mangle)]
518pub extern "C" fn grantpt(fildes: c_int) -> c_int {
519 0
521}
522
523#[unsafe(no_mangle)]
526pub unsafe extern "C" fn initstate(seed: c_uint, state: *mut c_char, size: size_t) -> *mut c_char {
527 if size < 8 {
528 ptr::null_mut()
529 } else {
530 let mut random_state = random::state_lock();
531 let old_state = unsafe { random_state.save() };
532 random_state.n = match size {
533 0..=7 => unreachable!(), 8..=31 => 0,
535 32..=63 => 7,
536 64..=127 => 15,
537 128..=255 => 31,
538 _ => 63,
539 };
540
541 random_state.x_ptr = unsafe { (state.cast::<[u8; 4]>()).offset(1) };
542 unsafe { random_state.seed(seed) };
543 unsafe { random_state.save() };
544
545 old_state.cast::<_>()
546 }
547}
548
549#[unsafe(no_mangle)]
559pub unsafe extern "C" fn jrand48(xsubi: *mut c_ushort) -> c_long {
560 let params = rand48::params();
561 let xsubi_mut: &mut [c_ushort; 3] = unsafe { slice::from_raw_parts_mut(xsubi, 3) }
562 .try_into()
563 .unwrap();
564 let new_xsubi_value = params.step(xsubi_mut.into());
565 *xsubi_mut = new_xsubi_value.into();
566 new_xsubi_value.get_i32()
567}
568
569#[unsafe(no_mangle)]
571pub unsafe extern "C" fn l64a(value: c_long) -> *mut c_char {
572 let value_as_i32 = value as i32;
574
575 let num_output_digits = usize::try_from(6 - (value_as_i32.leading_zeros() + 4) / 6).unwrap();
581
582 unsafe { L64A_BUFFER.unsafe_set([0; 7]) };
584
585 for i in 0..num_output_digits {
586 let digit_value = c_char::try_from((value_as_i32 >> (6 * i)) & 63).unwrap();
588
589 (unsafe { L64A_BUFFER.unsafe_mut() })[i] = match digit_value {
590 0..=11 => {
591 46 + digit_value
593 }
594 12..=37 => {
595 53 + digit_value
597 }
598 38..=63 => {
599 59 + digit_value
601 }
602 _ => unreachable!(), };
604 }
605
606 unsafe { L64A_BUFFER.unsafe_mut().as_mut_ptr() }
607}
608
609#[unsafe(no_mangle)]
611pub extern "C" fn labs(i: c_long) -> c_long {
612 i.abs()
613}
614
615#[unsafe(no_mangle)]
625pub unsafe extern "C" fn lcong48(param: *mut c_ushort) {
626 let mut xsubi = rand48::xsubi_lock();
627 let mut params = rand48::params_mut();
628
629 let param_slice = unsafe { slice::from_raw_parts(param, 7) };
630
631 let xsubi_ref: &[c_ushort; 3] = param_slice[0..3].try_into().unwrap();
632 let a_ref: &[c_ushort; 3] = param_slice[3..6].try_into().unwrap();
633 let c = param_slice[6];
634
635 *xsubi = xsubi_ref.into();
636 params.set(a_ref, c);
637}
638
639#[repr(C)]
641pub struct ldiv_t {
642 quot: c_long,
643 rem: c_long,
644}
645
646#[unsafe(no_mangle)]
648pub extern "C" fn ldiv(numer: c_long, denom: c_long) -> ldiv_t {
649 ldiv_t {
650 quot: numer / denom,
651 rem: numer % denom,
652 }
653}
654
655#[unsafe(no_mangle)]
657pub extern "C" fn llabs(i: c_longlong) -> c_longlong {
658 i.abs()
659}
660
661#[repr(C)]
663pub struct lldiv_t {
664 quot: c_longlong,
665 rem: c_longlong,
666}
667
668#[unsafe(no_mangle)]
670pub extern "C" fn lldiv(numer: c_longlong, denom: c_longlong) -> lldiv_t {
671 lldiv_t {
672 quot: numer / denom,
673 rem: numer % denom,
674 }
675}
676
677#[unsafe(no_mangle)]
683pub extern "C" fn lrand48() -> c_long {
684 let params = rand48::params();
685 let mut xsubi = rand48::xsubi_lock();
686 *xsubi = params.step(*xsubi);
687 xsubi.get_u31()
688}
689
690#[unsafe(no_mangle)]
692pub unsafe extern "C" fn malloc(size: size_t) -> *mut c_void {
693 let ptr = unsafe { platform::alloc(size) };
694 if ptr.is_null() {
695 platform::ERRNO.set(ENOMEM);
696 }
697 ptr
698}
699
700#[deprecated]
702#[unsafe(no_mangle)]
703pub unsafe extern "C" fn memalign(alignment: size_t, size: size_t) -> *mut c_void {
704 if alignment.is_power_of_two() {
705 let ptr = unsafe { platform::alloc_align(size, alignment) };
706 if ptr.is_null() {
707 platform::ERRNO.set(ENOMEM);
708 }
709 ptr
710 } else {
711 platform::ERRNO.set(EINVAL);
712 ptr::null_mut()
713 }
714}
715
716#[unsafe(no_mangle)]
718pub unsafe extern "C" fn mblen(s: *const c_char, n: size_t) -> c_int {
719 let mut wc: wchar_t = 0;
720 let mut state: mbstate_t = mbstate_t {};
721 let result: usize = unsafe { mbrtowc(&raw mut wc, s, n, &raw mut state) };
722
723 if result == -1isize as usize {
724 return -1;
725 }
726 if result == -2isize as usize {
727 return -1;
728 }
729
730 result as i32
731}
732
733#[unsafe(no_mangle)]
735pub unsafe extern "C" fn mbstowcs(pwcs: *mut wchar_t, mut s: *const c_char, n: size_t) -> size_t {
736 let mut state: mbstate_t = mbstate_t {};
737 unsafe { mbsrtowcs(pwcs, &raw mut s, n, &raw mut state) }
738}
739
740#[unsafe(no_mangle)]
742pub unsafe extern "C" fn mbtowc(pwc: *mut wchar_t, s: *const c_char, n: size_t) -> c_int {
743 let mut state: mbstate_t = mbstate_t {};
744 (unsafe { mbrtowc(pwc, s, n, &raw mut state) }) as c_int
745}
746
747fn inner_mktemp<T, F>(name: *mut c_char, suffix_len: c_int, mut attempt: F) -> Option<T>
748where
749 F: FnMut() -> Option<T>,
750{
751 let len = unsafe { strlen(name) as c_int };
752
753 if len < 6 || suffix_len > len - 6 {
754 platform::ERRNO.set(errno::EINVAL);
755 return None;
756 }
757
758 for i in (len - suffix_len - 6)..(len - suffix_len) {
759 if unsafe { *name.offset(i as isize) } != ByteLiteral::cast_cchar(b'X') {
760 platform::ERRNO.set(errno::EINVAL);
761 return None;
762 }
763 }
764
765 let mut rng = JitterRng::new_with_timer(get_nstime);
766 let _ = rng.test_timer();
767
768 for _ in 0..100 {
769 let char_iter = iter::repeat(())
770 .map(|()| rng.sample(Alphanumeric))
771 .take(6)
772 .enumerate();
773 unsafe {
774 for (i, c) in char_iter {
775 *name.offset((len as isize) - (suffix_len as isize) - (i as isize) - 1) =
776 c as c_char
777 }
778 }
779
780 if let result @ Some(_) = attempt() {
781 return result;
782 }
783 }
784
785 platform::ERRNO.set(errno::EEXIST);
786
787 None
788}
789
790fn get_nstime() -> u64 {
791 unsafe {
792 let mut ts = mem::MaybeUninit::uninit();
793 if Sys::clock_gettime(CLOCK_MONOTONIC, Out::from_uninit_mut(&mut ts)).is_ok() {}; ts.assume_init().tv_nsec as u64
795 }
796}
797
798#[unsafe(no_mangle)]
800pub unsafe extern "C" fn mkdtemp(name: *mut c_char) -> *mut c_char {
801 inner_mktemp(name, 0, || {
802 let name_c = unsafe { CStr::from_ptr(name) };
803 match Sys::mkdir(name_c, 0o700) {
804 Ok(()) => Some(name),
805 Err(_) => None,
806 }
807 })
808 .unwrap_or(ptr::null_mut())
809}
810
811#[unsafe(no_mangle)]
813pub unsafe extern "C" fn mkostemp(name: *mut c_char, flags: c_int) -> c_int {
814 unsafe { mkostemps(name, 0, flags) }
815}
816
817#[unsafe(no_mangle)]
819pub unsafe extern "C" fn mkostemps(
820 name: *mut c_char,
821 suffix_len: c_int,
822 mut flags: c_int,
823) -> c_int {
824 flags &= !O_ACCMODE;
827 flags |= O_RDWR | O_CREAT | O_EXCL;
828
829 inner_mktemp(name, suffix_len, || {
830 let name = unsafe { CStr::from_ptr(name) };
831 let fd = Sys::open(name, flags, 0o600).or_minus_one_errno();
832
833 if fd >= 0 { Some(fd) } else { None }
834 })
835 .unwrap_or(-1)
836}
837
838#[unsafe(no_mangle)]
840pub unsafe extern "C" fn mkstemp(name: *mut c_char) -> c_int {
841 unsafe { mkostemps(name, 0, 0) }
842}
843
844#[unsafe(no_mangle)]
846pub unsafe extern "C" fn mkstemps(name: *mut c_char, suffix_len: c_int) -> c_int {
847 unsafe { mkostemps(name, suffix_len, 0) }
848}
849
850#[deprecated]
856#[unsafe(no_mangle)]
857pub unsafe extern "C" fn mktemp(name: *mut c_char) -> *mut c_char {
858 if inner_mktemp(name, 0, || {
859 let name = unsafe { CStr::from_ptr(name) };
860 if Sys::access(name, 0) == Err(Errno(ENOENT)) {
861 Some(())
862 } else {
863 None
864 }
865 })
866 .is_none()
867 {
868 unsafe { *name = 0 };
869 }
870 name
871}
872
873#[unsafe(no_mangle)]
879pub extern "C" fn mrand48() -> c_long {
880 let params = rand48::params();
881 let mut xsubi = rand48::xsubi_lock();
882 *xsubi = params.step(*xsubi);
883 xsubi.get_i32()
884}
885
886#[unsafe(no_mangle)]
896pub unsafe extern "C" fn nrand48(xsubi: *mut c_ushort) -> c_long {
897 let params = rand48::params();
898 let xsubi_mut: &mut [c_ushort; 3] = unsafe { slice::from_raw_parts_mut(xsubi, 3) }
899 .try_into()
900 .unwrap();
901 let new_xsubi_value = params.step(xsubi_mut.into());
902 *xsubi_mut = new_xsubi_value.into();
903 new_xsubi_value.get_u31()
904}
905
906#[unsafe(no_mangle)]
908pub unsafe extern "C" fn posix_memalign(
909 memptr: *mut *mut c_void,
910 alignment: size_t,
911 size: size_t,
912) -> c_int {
913 const VOID_PTR_SIZE: usize = mem::size_of::<*mut c_void>();
914
915 if alignment.is_multiple_of(VOID_PTR_SIZE) && alignment.is_power_of_two() {
916 let ptr = unsafe { platform::alloc_align(size, alignment) };
917 unsafe { *memptr = ptr };
918 if ptr.is_null() { ENOMEM } else { 0 }
919 } else {
920 unsafe { *memptr = ptr::null_mut() };
921 EINVAL
922 }
923}
924
925#[unsafe(no_mangle)]
927pub unsafe extern "C" fn posix_openpt(flags: c_int) -> c_int {
928 #[cfg(target_os = "redox")]
929 let r = unsafe { open(c"/scheme/pty/ptmx".as_ptr(), flags) };
930 #[cfg(target_os = "linux")]
931 let r = unsafe { open(c"/dev/ptmx".as_ptr(), flags) };
932
933 if r < 0 && platform::ERRNO.get() == ENOSPC {
934 platform::ERRNO.set(EAGAIN);
935 }
936
937 r
938}
939
940#[unsafe(no_mangle)]
942pub unsafe extern "C" fn ptsname(fd: c_int) -> *mut c_char {
943 const PTS_BUFFER_LEN: usize = limits::TTY_NAME_MAX as usize;
944 static mut PTS_BUFFER: [c_char; PTS_BUFFER_LEN] = [0; PTS_BUFFER_LEN];
945 let ret = unsafe { ptsname_r(fd, (&raw mut PTS_BUFFER).cast(), PTS_BUFFER_LEN) };
946 if ret != 0 {
947 platform::ERRNO.set(ret);
948 ptr::null_mut()
949 } else {
950 (&raw mut PTS_BUFFER).cast()
951 }
952}
953
954#[unsafe(no_mangle)]
956pub unsafe extern "C" fn ptsname_r(fd: c_int, buf: *mut c_char, buflen: size_t) -> c_int {
957 if buf.is_null() {
958 platform::ERRNO.set(EINVAL);
959 EINVAL
960 } else {
961 unsafe { __ptsname_r(fd, buf, buflen) }
962 }
963}
964
965#[inline(always)]
967unsafe fn __ptsname_r(fd: c_int, buf: *mut c_char, buflen: size_t) -> c_int {
968 let mut pty: c_int = 0;
969
970 if unsafe { ioctl(fd, TIOCGPTN, ptr::from_mut(&mut pty).cast::<c_void>()) } == 0 {
971 #[cfg(target_os = "linux")]
973 let name = format!("/dev/pts/{}", pty);
974 #[cfg(target_os = "redox")]
975 let name = format!("/scheme/pty/{}", pty);
976 let len = name.len();
977 if len + 1 > buflen {
979 ERANGE
980 } else {
981 let s = name.as_ptr().cast();
984 unsafe { ptr::copy_nonoverlapping(s, buf, len) };
985 unsafe { *(buf.add(len + 1)) = 0 };
987 0
988 }
989 } else {
990 platform::ERRNO.get()
991 }
992}
993
994unsafe fn put_new_env(insert: *mut c_char) {
995 if unsafe { platform::environ } == unsafe { platform::OUR_ENVIRON.unsafe_mut().as_mut_ptr() } {
998 {
999 let our_environ = unsafe { &mut *platform::OUR_ENVIRON.as_mut_ptr() };
1000 *our_environ.last_mut().unwrap() = insert;
1001 our_environ.push(core::ptr::null_mut());
1002 }
1003 unsafe { platform::environ = platform::OUR_ENVIRON.unsafe_mut().as_mut_ptr() };
1005 } else {
1006 {
1007 let our_environ = unsafe { &mut *platform::OUR_ENVIRON.as_mut_ptr() };
1008 our_environ.clear();
1009 our_environ.extend(platform::environ_iter());
1010 our_environ.push(insert);
1011 our_environ.push(core::ptr::null_mut());
1012 }
1013 unsafe { platform::environ = platform::OUR_ENVIRON.unsafe_mut().as_mut_ptr() };
1014 }
1015}
1016
1017#[unsafe(no_mangle)]
1019pub unsafe extern "C" fn putenv(insert: *mut c_char) -> c_int {
1020 assert_ne!(insert, ptr::null_mut(), "putenv(NULL)");
1021 if let Some((i, _)) = unsafe { find_env(insert) } {
1022 unsafe { platform::environ.add(i).write(insert) };
1026 } else {
1027 unsafe { put_new_env(insert) };
1028 }
1029 0
1030}
1031
1032#[unsafe(no_mangle)]
1034pub unsafe extern "C" fn qsort(
1035 base: *mut c_void,
1036 nel: size_t,
1037 width: size_t,
1038 compar: Option<extern "C" fn(*const c_void, *const c_void) -> c_int>,
1039) {
1040 if let Some(comp) = compar {
1041 if nel > 0 {
1043 let mut ctx = QsortContext { comp };
1046 unsafe { sort::introsort(base.cast::<c_char>(), nel, width, &mut ctx) };
1047 }
1048 }
1049}
1050
1051#[unsafe(no_mangle)]
1053pub unsafe extern "C" fn qsort_r(
1054 base: *mut c_void,
1055 nel: size_t,
1056 width: size_t,
1057 compar: Option<extern "C" fn(*const c_void, *const c_void, *mut c_void) -> c_int>,
1058 arg: *mut c_void,
1059) {
1060 if let (Some(comp), true) = (compar, nel > 0) {
1061 let mut ctx = QsortRContext { comp, arg };
1062 unsafe { sort::introsort(base.cast::<c_char>(), nel, width, &mut ctx) };
1063 }
1064}
1065
1066#[unsafe(no_mangle)]
1068pub unsafe extern "C" fn quick_exit(status: c_int) -> ! {
1069 for i in (0..unsafe { AT_QUICK_EXIT_FUNCS.unsafe_ref() }.len()).rev() {
1070 if let Some(func) = unsafe { AT_QUICK_EXIT_FUNCS.unsafe_ref() }[i] {
1071 (func)();
1072 }
1073 }
1074
1075 Sys::exit(status);
1076}
1077
1078#[unsafe(no_mangle)]
1080pub unsafe extern "C" fn rand() -> c_int {
1081 unsafe {
1082 match RNG {
1083 Some(ref mut rng) => rng_sampler().sample(rng),
1084 None => {
1085 let mut rng = XorShiftRng::from_seed([1; 16]);
1086 let ret = rng_sampler().sample(&mut rng);
1087 RNG = Some(rng);
1088 ret
1089 }
1090 }
1091 }
1092}
1093
1094#[deprecated]
1100#[unsafe(no_mangle)]
1101pub unsafe extern "C" fn rand_r(seed: *mut c_uint) -> c_int {
1102 if seed.is_null() {
1103 errno::EINVAL
1104 } else {
1105 let seed_arr: [u8; 16] = unsafe { mem::transmute([*seed; 16 / mem::size_of::<c_uint>()]) };
1107
1108 let mut rng = XorShiftRng::from_seed(seed_arr);
1109 let ret = rng_sampler().sample(&mut rng);
1110
1111 unsafe { *seed = ret as _ };
1112
1113 ret
1114 }
1115}
1116
1117#[unsafe(no_mangle)]
1120pub unsafe extern "C" fn random() -> c_long {
1121 let mut random_state = random::state_lock();
1122
1123 let k: u32;
1124
1125 unsafe { random_state.ensure_x_ptr_init() };
1126
1127 if random_state.n == 0 {
1128 let x_old = u32::from_ne_bytes(unsafe { *random_state.x_ptr });
1129 let x_new = random::lcg31_step(x_old);
1130 unsafe { *random_state.x_ptr = x_new.to_ne_bytes() };
1131 k = x_new;
1132 } else {
1133 let x_i_old =
1135 u32::from_ne_bytes(unsafe { *random_state.x_ptr.add(usize::from(random_state.i)) });
1136 let x_j =
1137 u32::from_ne_bytes(unsafe { *random_state.x_ptr.add(usize::from(random_state.j)) });
1138 let x_i_new = x_i_old.wrapping_add(x_j);
1139 unsafe { *random_state.x_ptr.add(usize::from(random_state.i)) = x_i_new.to_ne_bytes() };
1140
1141 k = x_i_new >> 1;
1142
1143 random_state.i += 1;
1144 if random_state.i == random_state.n {
1145 random_state.i = 0;
1146 }
1147
1148 random_state.j += 1;
1149 if random_state.j == random_state.n {
1150 random_state.j = 0;
1151 }
1152 }
1153
1154 #[cfg(not(target_arch = "x86"))]
1157 return c_long::from(k);
1158 #[cfg(target_arch = "x86")] c_long::try_from(k).unwrap()
1160}
1161
1162#[unsafe(no_mangle)]
1164pub unsafe extern "C" fn realloc(ptr: *mut c_void, size: size_t) -> *mut c_void {
1165 let new_ptr = unsafe { platform::realloc(ptr, size) };
1166 if new_ptr.is_null() {
1167 platform::ERRNO.set(ENOMEM);
1168 }
1169 new_ptr
1170}
1171
1172#[unsafe(no_mangle)]
1174pub unsafe extern "C" fn reallocarray(ptr: *mut c_void, m: size_t, n: size_t) -> *mut c_void {
1175 match m.checked_mul(n) {
1177 Some(size) => unsafe { realloc(ptr, size) },
1178 None => {
1179 platform::ERRNO.set(ENOMEM);
1181 ptr::null_mut()
1182 }
1183 }
1184}
1185
1186#[unsafe(no_mangle)]
1188pub unsafe extern "C" fn realpath(pathname: *const c_char, resolved: *mut c_char) -> *mut c_char {
1189 let ptr = if resolved.is_null() {
1190 (unsafe { malloc(limits::PATH_MAX) }).cast::<c_char>()
1191 } else {
1192 resolved
1193 };
1194
1195 let out = unsafe { slice::from_raw_parts_mut(ptr.cast::<u8>(), limits::PATH_MAX) };
1196 {
1197 let file = match File::open(unsafe { CStr::from_ptr(pathname) }, O_PATH | O_CLOEXEC) {
1198 Ok(file) => file,
1199 Err(_) => return ptr::null_mut(),
1200 };
1201
1202 let len = out.len();
1203 let read = Sys::fpath(*file, &mut out[..len - 1])
1205 .map(|read| read as ssize_t)
1206 .or_minus_one_errno();
1207 if read < 0 {
1208 return ptr::null_mut();
1209 }
1210 out[read as usize] = 0;
1211 }
1212
1213 ptr
1214}
1215
1216pub unsafe extern "C" fn secure_getenv(name: *const c_char) -> *mut c_char {
1219 unimplemented!();
1220}
1221
1222#[unsafe(no_mangle)]
1234pub unsafe extern "C" fn seed48(seed16v: *mut c_ushort) -> *mut c_ushort {
1235 static RETURN_BUFFER: RawCell<[c_ushort; 3]> = RawCell::new([0; 3]);
1236
1237 let mut params = rand48::params_mut();
1238 let mut xsubi = rand48::xsubi_lock();
1239
1240 let seed16v_ref: &[c_ushort; 3] = unsafe { slice::from_raw_parts(seed16v, 3) }
1243 .try_into()
1244 .unwrap();
1245
1246 let return_buffer_mut = unsafe { RETURN_BUFFER.unsafe_mut() };
1249 *return_buffer_mut = (*xsubi).into();
1250 *xsubi = seed16v_ref.into();
1251 params.reset();
1252 RETURN_BUFFER.as_mut_ptr().cast()
1253}
1254
1255unsafe fn copy_kv(
1256 existing: *mut c_char,
1257 key: *const c_char,
1258 value: *const c_char,
1259 key_len: usize,
1260 value_len: usize,
1261) {
1262 unsafe { core::ptr::copy_nonoverlapping(key, existing, key_len) };
1263 unsafe { core::ptr::write(existing.add(key_len), ByteLiteral::cast_cchar(b'=')) };
1264 unsafe { core::ptr::copy_nonoverlapping(value, existing.add(key_len + 1), value_len) };
1265 unsafe { core::ptr::write(existing.add(key_len + 1 + value_len), 0) };
1266}
1267
1268#[unsafe(no_mangle)]
1270pub unsafe extern "C" fn setenv(
1271 key: *const c_char,
1272 value: *const c_char,
1273 overwrite: c_int,
1274) -> c_int {
1275 let key_len = unsafe { strlen(key) };
1276 let value_len = unsafe { strlen(value) };
1277
1278 if let Some((i, existing)) = unsafe { find_env(key) } {
1279 if overwrite == 0 {
1280 return 0;
1281 }
1282
1283 let existing_len = unsafe { strlen(existing) };
1284
1285 if existing_len >= value_len {
1286 unsafe { core::ptr::copy_nonoverlapping(value, existing, value_len) };
1288 unsafe { core::ptr::write(existing.add(value_len), 0) };
1290 } else {
1291 let ptr = unsafe { platform::alloc(key_len as usize + 1 + value_len as usize + 1) }
1293 .cast::<c_char>();
1294 unsafe { copy_kv(ptr, key, value, key_len, value_len) };
1295 unsafe { platform::environ.add(i).write(ptr) };
1296 }
1297 } else {
1298 let ptr = unsafe { platform::alloc(key_len as usize + 1 + value_len as usize + 1) }
1300 .cast::<c_char>();
1301 unsafe { copy_kv(ptr, key, value, key_len, value_len) };
1302 unsafe { put_new_env(ptr) };
1303 }
1304
1305 0
1308}
1309
1310#[deprecated]
1316pub unsafe extern "C" fn setkey(key: *const c_char) {
1318 unimplemented!();
1319}
1320
1321#[unsafe(no_mangle)]
1324pub unsafe extern "C" fn setstate(state: *mut c_char) -> *mut c_char {
1325 let mut random_state = random::state_lock();
1326
1327 let old_state = unsafe { random_state.save() };
1328 unsafe { random_state.load(state.cast::<_>()) };
1329
1330 old_state.cast::<_>()
1331}
1332
1333#[unsafe(no_mangle)]
1335pub unsafe extern "C" fn srand(seed: c_uint) {
1336 unsafe { RNG = Some(XorShiftRng::from_seed([seed as u8; 16])) };
1337}
1338
1339#[unsafe(no_mangle)]
1345pub extern "C" fn srand48(seedval: c_long) {
1346 let mut params = rand48::params_mut();
1347 let mut xsubi = rand48::xsubi_lock();
1348
1349 params.reset();
1350 *xsubi = ((u64::from(seedval as u32) << 16) | 0x330e)
1354 .try_into()
1355 .unwrap();
1356}
1357
1358#[unsafe(no_mangle)]
1361pub unsafe extern "C" fn srandom(seed: c_uint) {
1362 let mut random_state = random::state_lock();
1363
1364 unsafe { random_state.seed(seed) };
1365}
1366
1367pub fn is_positive(ch: c_char) -> Option<(bool, isize)> {
1368 match ch {
1369 0 => None,
1370 ch if ch == ByteLiteral::cast_cchar(b'+') => Some((true, 1)),
1371 ch if ch == ByteLiteral::cast_cchar(b'-') => Some((false, 1)),
1372 _ => Some((true, 0)),
1373 }
1374}
1375
1376pub unsafe fn detect_base(s: *const c_char) -> Option<(c_int, isize)> {
1377 let first = unsafe { *s } as u8;
1378 match first {
1379 0 => None,
1380 b'0' => {
1381 let second = unsafe { *s.offset(1) } as u8;
1382 if second == b'X' || second == b'x' {
1383 Some((16, 2))
1384 } else if (b'0'..=b'7').contains(&second) {
1385 Some((8, 1))
1386 } else {
1387 Some((8, 0))
1389 }
1390 }
1391 _ => Some((10, 0)),
1392 }
1393}
1394
1395pub unsafe fn convert_octal(s: *const c_char) -> Option<(c_ulong, isize, bool)> {
1396 if unsafe { *s } != 0 && unsafe { *s } == ByteLiteral::cast_cchar(b'0') {
1397 if let Some((val, idx, overflow)) = unsafe { convert_integer(s.offset(1), 8) } {
1398 Some((val, idx + 1, overflow))
1399 } else {
1400 Some((0, 1, false))
1402 }
1403 } else {
1404 None
1405 }
1406}
1407
1408pub unsafe fn convert_hex(s: *const c_char) -> Option<(c_ulong, isize, bool)> {
1409 if (unsafe { *s } != 0 && unsafe { *s } == ByteLiteral::cast_cchar(b'0'))
1410 && (unsafe { *s.offset(1) } != 0
1411 && (unsafe { *s.offset(1) } == ByteLiteral::cast_cchar(b'x')
1412 || unsafe { *s.offset(1) } == ByteLiteral::cast_cchar(b'X')))
1413 {
1414 unsafe { convert_integer(s.offset(2), 16) }
1415 .map(|(val, idx, overflow)| (val, idx + 2, overflow))
1416 } else {
1417 unsafe { convert_integer(s, 16) }
1418 }
1419}
1420
1421pub unsafe fn convert_integer(s: *const c_char, base: c_int) -> Option<(c_ulong, isize, bool)> {
1422 #[rustfmt::skip]
1424 const LOOKUP_TABLE: [c_long; 256] = [
1425 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1426 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1427 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1428 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
1429 -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
1430 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
1431 -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
1432 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
1433 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1434 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1435 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1436 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1437 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1438 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1439 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1440 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1441 ];
1442
1443 let mut num: c_ulong = 0;
1444 let mut idx = 0;
1445 let mut overflowed = false;
1446
1447 loop {
1448 let val = LOOKUP_TABLE[unsafe { *s.offset(idx) } as u8 as usize];
1452 if val == -1 || val as c_int >= base {
1453 break;
1454 } else {
1455 if let Some(res) = num
1456 .checked_mul(base as c_ulong)
1457 .and_then(|num| num.checked_add(val as c_ulong))
1458 {
1459 num = res;
1460 } else {
1461 platform::ERRNO.set(ERANGE);
1462 num = c_ulong::MAX;
1463 overflowed = true;
1464 }
1465
1466 idx += 1;
1467 }
1468 }
1469
1470 if idx > 0 {
1471 Some((num, idx, overflowed))
1472 } else {
1473 None
1474 }
1475}
1476
1477#[expect(clippy::cast_lossless)] #[unsafe(no_mangle)]
1480pub unsafe extern "C" fn strtod(s: *const c_char, endptr: *mut *mut c_char) -> c_double {
1481 strto_float_impl!(c_double, s, endptr)
1482}
1483
1484#[unsafe(no_mangle)]
1486pub unsafe extern "C" fn strtof(s: *const c_char, endptr: *mut *mut c_char) -> c_float {
1487 strto_float_impl!(c_float, s, endptr)
1488}
1489
1490#[unsafe(no_mangle)]
1498pub unsafe extern "C" fn strtol(
1499 nptr: *const c_char,
1500 endptr: *mut *mut c_char,
1501 base: c_int,
1502) -> c_long {
1503 strto_impl!(c_long, true, c_long::MAX, c_long::MIN, nptr, endptr, base)
1504}
1505
1506#[unsafe(no_mangle)]
1516pub unsafe extern "C" fn strtoll(
1517 nptr: *const c_char,
1518 endptr: *mut *mut c_char,
1519 base: c_int,
1520) -> c_longlong {
1521 strto_impl!(
1522 c_longlong,
1523 true,
1524 c_longlong::MAX,
1525 c_longlong::MIN,
1526 nptr,
1527 endptr,
1528 base
1529 )
1530}
1531
1532#[unsafe(no_mangle)]
1540pub unsafe extern "C" fn strtoul(
1541 str: *const c_char,
1542 endptr: *mut *mut c_char,
1543 base: c_int,
1544) -> c_ulong {
1545 strto_impl!(
1546 c_ulong,
1547 false,
1548 c_ulong::MAX,
1549 c_ulong::MIN,
1550 str,
1551 endptr,
1552 base
1553 )
1554}
1555
1556#[unsafe(no_mangle)]
1564pub unsafe extern "C" fn strtoull(
1565 str: *const c_char,
1566 endptr: *mut *mut c_char,
1567 base: c_int,
1568) -> c_ulonglong {
1569 strto_impl!(
1570 c_ulonglong,
1571 false,
1572 c_ulonglong::MAX,
1573 c_ulonglong::MIN,
1574 str,
1575 endptr,
1576 base
1577 )
1578}
1579
1580#[unsafe(no_mangle)]
1582pub unsafe extern "C" fn system(command: *const c_char) -> c_int {
1583 if command.is_null() {
1588 let status = unsafe { system(c"exit 0".as_ptr().cast::<c_char>()) };
1589 if status == 0 {
1590 return 1;
1591 } else {
1592 return 0;
1593 }
1594 }
1595
1596 let child_pid = unsafe { unistd::fork() };
1597 if child_pid == 0 {
1598 let command_nonnull = command.cast::<c_char>();
1599
1600 let shell = c"/bin/sh".as_ptr();
1601
1602 let args = [c"sh".as_ptr(), c"-c".as_ptr(), command_nonnull, ptr::null()];
1603
1604 unsafe { unistd::execv(shell.cast::<c_char>(), args.as_ptr().cast::<*mut c_char>()) };
1605
1606 unsafe { exit(127) };
1607
1608 unreachable!();
1609 } else if child_pid > 0 {
1610 let mut wstatus = 0;
1611 if Sys::waitpid(child_pid, Some(Out::from_mut(&mut wstatus)), 0).or_minus_one_errno() == -1
1612 {
1613 return -1;
1614 }
1615
1616 wstatus
1617 } else {
1618 -1
1619 }
1620}
1621
1622#[deprecated]
1628pub extern "C" fn ttyslot() -> c_int {
1630 unimplemented!();
1631}
1632
1633#[unsafe(no_mangle)]
1635pub unsafe extern "C" fn unlockpt(fildes: c_int) -> c_int {
1636 let mut u: c_int = 0;
1637 unsafe {
1638 ioctl(
1639 fildes,
1640 TIOCSPTLCK,
1641 ptr::from_mut::<i32>(&mut u).cast::<c_void>(),
1642 )
1643 }
1644}
1645
1646#[unsafe(no_mangle)]
1648pub unsafe extern "C" fn unsetenv(key: *const c_char) -> c_int {
1649 if let Some((i, _)) = unsafe { find_env(key) } {
1650 if unsafe { platform::environ }
1651 == unsafe { platform::OUR_ENVIRON.unsafe_mut().as_mut_ptr() }
1652 {
1653 {
1656 let our_environ = unsafe { &mut *platform::OUR_ENVIRON.as_mut_ptr() };
1657 our_environ.remove(i);
1658 }
1659
1660 unsafe { platform::environ = platform::OUR_ENVIRON.unsafe_mut().as_mut_ptr() };
1662 } else {
1663 {
1664 let our_environ = unsafe { &mut *platform::OUR_ENVIRON.as_mut_ptr() };
1665 our_environ.clear();
1666 our_environ.extend(
1667 platform::environ_iter()
1668 .enumerate()
1669 .filter(|&(j, _)| j != i)
1670 .map(|(_, v)| v),
1671 );
1672 our_environ.push(core::ptr::null_mut());
1673 }
1674 unsafe { platform::environ = platform::OUR_ENVIRON.unsafe_mut().as_mut_ptr() };
1675 }
1676 }
1677 0
1678}
1679
1680#[deprecated]
1686#[unsafe(no_mangle)]
1687pub unsafe extern "C" fn valloc(size: size_t) -> *mut c_void {
1688 match size_t::try_from(unsafe { sysconf(_SC_PAGESIZE) }) {
1691 Ok(page_size) => {
1692 let ptr = unsafe { platform::alloc_align(size, page_size) };
1695 if ptr.is_null() {
1696 platform::ERRNO.set(ENOMEM);
1697 }
1698 ptr
1699 }
1700 Err(_) => {
1701 ptr::null_mut()
1703 }
1704 }
1705}
1706
1707#[unsafe(no_mangle)]
1709pub unsafe extern "C" fn wcstombs(s: *mut c_char, mut pwcs: *const wchar_t, n: size_t) -> size_t {
1710 let mut state: mbstate_t = mbstate_t {};
1711 unsafe { wcsrtombs(s, &raw mut pwcs, n, &raw mut state) }
1712}
1713
1714#[unsafe(no_mangle)]
1716pub unsafe extern "C" fn wctomb(s: *mut c_char, wc: wchar_t) -> c_int {
1717 let mut state: mbstate_t = mbstate_t {};
1718 let result: usize = unsafe { wcrtomb(s, wc, &raw mut state) };
1719
1720 if result == -1isize as usize {
1721 return -1;
1722 }
1723 if result == -2isize as usize {
1724 return -1;
1725 }
1726
1727 result as c_int
1728}