2
0

mod.rs 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079
  1. //! stdlib implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/stdlib.h.html
  2. use core::convert::TryFrom;
  3. use core::{intrinsics, iter, mem, ptr, slice};
  4. use rand::distributions::{Alphanumeric, Distribution, Uniform};
  5. use rand::prng::XorShiftRng;
  6. use rand::rngs::JitterRng;
  7. use rand::{Rng, SeedableRng};
  8. use c_str::CStr;
  9. use fs::File;
  10. use header::errno::*;
  11. use header::fcntl::*;
  12. use header::limits;
  13. use header::string::*;
  14. use header::time::constants::CLOCK_MONOTONIC;
  15. use header::time::timespec;
  16. use header::unistd::{sysconf, _SC_PAGESIZE};
  17. use header::wchar::*;
  18. use header::{ctype, errno, unistd};
  19. use platform;
  20. use platform::types::*;
  21. use platform::{Pal, Sys};
  22. mod lcg48;
  23. mod sort;
  24. pub const EXIT_FAILURE: c_int = 1;
  25. pub const EXIT_SUCCESS: c_int = 0;
  26. pub const RAND_MAX: c_int = 2_147_483_647;
  27. //Maximum number of bytes in a multibyte character for the current locale
  28. pub const MB_CUR_MAX: c_int = 4;
  29. //Maximum number of bytes in a multibyte characters for any locale
  30. pub const MB_LEN_MAX: c_int = 4;
  31. static mut ATEXIT_FUNCS: [Option<extern "C" fn()>; 32] = [None; 32];
  32. static mut RNG: Option<XorShiftRng> = None;
  33. lazy_static! {
  34. static ref RNG_SAMPLER: Uniform<c_int> = Uniform::new_inclusive(0, RAND_MAX);
  35. }
  36. #[no_mangle]
  37. pub extern "C" fn _Exit(status: c_int) {
  38. unistd::_exit(status);
  39. }
  40. #[no_mangle]
  41. pub unsafe extern "C" fn a64l(s: *const c_char) -> c_long {
  42. if s.is_null() {
  43. return 0;
  44. }
  45. let mut l: c_long = 0;
  46. // a64l does not support more than 6 characters at once
  47. for x in 0..6 {
  48. let c = *s.offset(x);
  49. if c == 0 {
  50. // string is null terminated
  51. return l;
  52. }
  53. // ASCII to base64 conversion:
  54. let mut bits: c_long = if c < 58 {
  55. (c - 46) as c_long // ./0123456789
  56. } else if c < 91 {
  57. (c - 53) as c_long // A-Z
  58. } else {
  59. (c - 59) as c_long // a-z
  60. };
  61. bits <<= 6 * x;
  62. l |= bits;
  63. }
  64. l
  65. }
  66. #[no_mangle]
  67. pub unsafe extern "C" fn abort() {
  68. intrinsics::abort();
  69. }
  70. #[no_mangle]
  71. pub extern "C" fn abs(i: c_int) -> c_int {
  72. i.abs()
  73. }
  74. #[no_mangle]
  75. pub unsafe extern "C" fn aligned_alloc(alignment: size_t, size: size_t) -> *mut c_void {
  76. if size % alignment == 0 {
  77. /* The size-is-multiple-of-alignment requirement is the only
  78. * difference between aligned_alloc() and memalign(). */
  79. memalign(alignment, size)
  80. } else {
  81. platform::errno = errno::EINVAL;
  82. ptr::null_mut()
  83. }
  84. }
  85. #[no_mangle]
  86. pub unsafe extern "C" fn atexit(func: Option<extern "C" fn()>) -> c_int {
  87. for i in 0..ATEXIT_FUNCS.len() {
  88. if ATEXIT_FUNCS[i] == None {
  89. ATEXIT_FUNCS[i] = func;
  90. return 0;
  91. }
  92. }
  93. 1
  94. }
  95. #[no_mangle]
  96. pub unsafe extern "C" fn atof(s: *const c_char) -> c_double {
  97. strtod(s, ptr::null_mut())
  98. }
  99. macro_rules! dec_num_from_ascii {
  100. ($s:expr, $t:ty) => {
  101. unsafe {
  102. let mut s = $s;
  103. // Iterate past whitespace
  104. while ctype::isspace(*s as c_int) != 0 {
  105. s = s.offset(1);
  106. }
  107. // Find out if there is a - sign
  108. let neg_sign = match *s {
  109. 0x2d => {
  110. s = s.offset(1);
  111. true
  112. }
  113. // '+' increment s and continue parsing
  114. 0x2b => {
  115. s = s.offset(1);
  116. false
  117. }
  118. _ => false,
  119. };
  120. let mut n: $t = 0;
  121. while ctype::isdigit(*s as c_int) != 0 {
  122. n = 10 * n - (*s as $t - 0x30);
  123. s = s.offset(1);
  124. }
  125. if neg_sign {
  126. n
  127. } else {
  128. -n
  129. }
  130. }
  131. };
  132. }
  133. #[no_mangle]
  134. pub extern "C" fn atoi(s: *const c_char) -> c_int {
  135. dec_num_from_ascii!(s, c_int)
  136. }
  137. #[no_mangle]
  138. pub extern "C" fn atol(s: *const c_char) -> c_long {
  139. dec_num_from_ascii!(s, c_long)
  140. }
  141. #[no_mangle]
  142. pub extern "C" fn atoll(s: *const c_char) -> c_longlong {
  143. dec_num_from_ascii!(s, c_longlong)
  144. }
  145. unsafe extern "C" fn void_cmp(a: *const c_void, b: *const c_void) -> c_int {
  146. *(a as *const i32) - *(b as *const i32) as c_int
  147. }
  148. #[no_mangle]
  149. pub unsafe extern "C" fn bsearch(
  150. key: *const c_void,
  151. base: *const c_void,
  152. nel: size_t,
  153. width: size_t,
  154. compar: Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>,
  155. ) -> *mut c_void {
  156. let mut start = base;
  157. let mut len = nel;
  158. let cmp_fn = compar.unwrap_or(void_cmp);
  159. while len > 0 {
  160. let med = (start as size_t + (len >> 1) * width) as *const c_void;
  161. let diff = cmp_fn(key, med);
  162. if diff == 0 {
  163. return med as *mut c_void;
  164. } else if diff > 0 {
  165. start = (med as usize + width) as *const c_void;
  166. len -= 1;
  167. }
  168. len >>= 1;
  169. }
  170. ptr::null_mut()
  171. }
  172. #[no_mangle]
  173. pub unsafe extern "C" fn calloc(nelem: size_t, elsize: size_t) -> *mut c_void {
  174. //Handle possible integer overflow in size calculation
  175. let size_result = nelem.checked_mul(elsize);
  176. match size_result {
  177. Some(size) => {
  178. /* If allocation fails here, errno setting will be handled
  179. * by malloc() */
  180. let ptr = malloc(size);
  181. if !ptr.is_null() {
  182. intrinsics::write_bytes(ptr as *mut u8, 0, size);
  183. }
  184. ptr
  185. }
  186. None => {
  187. // For overflowing multiplication, we have to set errno here
  188. platform::errno = errno::ENOMEM;
  189. ptr::null_mut()
  190. }
  191. }
  192. }
  193. #[repr(C)]
  194. pub struct div_t {
  195. quot: c_int,
  196. rem: c_int,
  197. }
  198. #[no_mangle]
  199. pub extern "C" fn div(numer: c_int, denom: c_int) -> div_t {
  200. div_t {
  201. quot: numer / denom,
  202. rem: numer % denom,
  203. }
  204. }
  205. #[no_mangle]
  206. pub unsafe extern "C" fn drand48() -> c_double {
  207. let new_xi = lcg48::generator_step(lcg48::DEFAULT_XI.as_mut_ptr());
  208. lcg48::float64_from_x(new_xi)
  209. }
  210. // #[no_mangle]
  211. pub extern "C" fn ecvt(
  212. value: c_double,
  213. ndigit: c_int,
  214. decpt: *mut c_int,
  215. sign: *mut c_int,
  216. ) -> *mut c_char {
  217. unimplemented!();
  218. }
  219. #[no_mangle]
  220. pub unsafe extern "C" fn erand48(xsubi: *mut c_ushort) -> c_double {
  221. let new_xi = lcg48::generator_step(xsubi);
  222. lcg48::float64_from_x(new_xi)
  223. }
  224. #[no_mangle]
  225. pub unsafe extern "C" fn exit(status: c_int) {
  226. extern "C" {
  227. static __fini_array_start: extern "C" fn();
  228. static __fini_array_end: extern "C" fn();
  229. fn pthread_terminate();
  230. fn _fini();
  231. }
  232. for i in (0..ATEXIT_FUNCS.len()).rev() {
  233. if let Some(func) = ATEXIT_FUNCS[i] {
  234. (func)();
  235. }
  236. }
  237. // Look for the neighbor functions in memory until the end
  238. let mut f = &__fini_array_end as *const _;
  239. #[allow(clippy::op_ref)]
  240. while f > &__fini_array_start {
  241. f = f.offset(-1);
  242. (*f)();
  243. }
  244. _fini();
  245. pthread_terminate();
  246. Sys::exit(status);
  247. }
  248. // #[no_mangle]
  249. pub extern "C" fn fcvt(
  250. value: c_double,
  251. ndigit: c_int,
  252. decpt: *mut c_int,
  253. sign: *mut c_int,
  254. ) -> *mut c_char {
  255. unimplemented!();
  256. }
  257. #[no_mangle]
  258. pub unsafe extern "C" fn free(ptr: *mut c_void) {
  259. platform::free(ptr);
  260. }
  261. // #[no_mangle]
  262. pub extern "C" fn gcvt(value: c_double, ndigit: c_int, buf: *mut c_char) -> *mut c_char {
  263. unimplemented!();
  264. }
  265. unsafe fn find_env(search: *const c_char) -> Option<(usize, *mut c_char)> {
  266. for (i, item) in platform::inner_environ.iter().enumerate() {
  267. let mut item = *item;
  268. if item.is_null() {
  269. assert_eq!(
  270. i,
  271. platform::inner_environ.len() - 1,
  272. "an early null pointer in environ vector"
  273. );
  274. break;
  275. }
  276. let mut search = search;
  277. loop {
  278. let end_of_query = *search == 0 || *search == b'=' as c_char;
  279. assert_ne!(*item, 0, "environ has an item without value");
  280. if *item == b'=' as c_char || end_of_query {
  281. if *item == b'=' as c_char && end_of_query {
  282. // Both keys env here
  283. return Some((i, item.offset(1)));
  284. } else {
  285. break;
  286. }
  287. }
  288. if *item != *search {
  289. break;
  290. }
  291. item = item.offset(1);
  292. search = search.offset(1);
  293. }
  294. }
  295. None
  296. }
  297. #[no_mangle]
  298. pub unsafe extern "C" fn getenv(name: *const c_char) -> *mut c_char {
  299. find_env(name).map(|val| val.1).unwrap_or(ptr::null_mut())
  300. }
  301. // #[no_mangle]
  302. pub extern "C" fn getsubopt(
  303. optionp: *mut *mut c_char,
  304. tokens: *const *mut c_char,
  305. valuep: *mut *mut c_char,
  306. ) -> c_int {
  307. unimplemented!();
  308. }
  309. // #[no_mangle]
  310. pub extern "C" fn grantpt(fildes: c_int) -> c_int {
  311. unimplemented!();
  312. }
  313. // #[no_mangle]
  314. pub extern "C" fn initstate(seec: c_uint, state: *mut c_char, size: size_t) -> *mut c_char {
  315. unimplemented!();
  316. }
  317. #[no_mangle]
  318. pub unsafe extern "C" fn jrand48(xsubi: *mut c_ushort) -> c_long {
  319. let new_xi = lcg48::generator_step(xsubi);
  320. lcg48::int32_from_x(new_xi)
  321. }
  322. // #[no_mangle]
  323. pub extern "C" fn l64a(value: c_long) -> *mut c_char {
  324. unimplemented!();
  325. }
  326. #[no_mangle]
  327. pub extern "C" fn labs(i: c_long) -> c_long {
  328. i.abs()
  329. }
  330. #[no_mangle]
  331. pub unsafe extern "C" fn lcong48(param: *mut c_ushort) {
  332. // Input should be a size-7 array.
  333. /* Go through this ptr -> u64 -> ptr conversion to ensure we only
  334. * get the lower 16 bits of each element. */
  335. let new_xi = lcg48::uint48_from_ushort_arr3(param.offset(0));
  336. lcg48::set_ushort_arr3_from_uint48(lcg48::DEFAULT_XI.as_mut_ptr(), new_xi);
  337. lcg48::A = lcg48::uint48_from_ushort_arr3(param.offset(3));
  338. lcg48::C = *param.offset(6) as u16; // c_ushort may be more than 16 bits
  339. }
  340. #[repr(C)]
  341. pub struct ldiv_t {
  342. quot: c_long,
  343. rem: c_long,
  344. }
  345. #[no_mangle]
  346. pub extern "C" fn ldiv(numer: c_long, denom: c_long) -> ldiv_t {
  347. ldiv_t {
  348. quot: numer / denom,
  349. rem: numer % denom,
  350. }
  351. }
  352. #[no_mangle]
  353. pub extern "C" fn llabs(i: c_longlong) -> c_longlong {
  354. i.abs()
  355. }
  356. #[repr(C)]
  357. pub struct lldiv_t {
  358. quot: c_longlong,
  359. rem: c_longlong,
  360. }
  361. #[no_mangle]
  362. pub extern "C" fn lldiv(numer: c_longlong, denom: c_longlong) -> lldiv_t {
  363. lldiv_t {
  364. quot: numer / denom,
  365. rem: numer % denom,
  366. }
  367. }
  368. #[no_mangle]
  369. pub unsafe extern "C" fn lrand48() -> c_long {
  370. let new_xi = lcg48::generator_step(lcg48::DEFAULT_XI.as_mut_ptr());
  371. lcg48::uint31_from_x(new_xi)
  372. }
  373. #[no_mangle]
  374. pub unsafe extern "C" fn malloc(size: size_t) -> *mut c_void {
  375. let ptr = platform::alloc(size);
  376. if ptr.is_null() {
  377. platform::errno = errno::ENOMEM;
  378. }
  379. ptr
  380. }
  381. #[no_mangle]
  382. pub unsafe extern "C" fn memalign(alignment: size_t, size: size_t) -> *mut c_void {
  383. /* Check if alignment is a (positive) power of two. The second
  384. * expression will never underflow, due to Rust's lazy boolean
  385. * operators. */
  386. if alignment > 0 && (alignment & (alignment - 1)) == 0 {
  387. let ptr = platform::alloc_align(size, alignment);
  388. if ptr.is_null() {
  389. platform::errno = errno::ENOMEM;
  390. }
  391. ptr
  392. } else {
  393. platform::errno = errno::EINVAL;
  394. ptr::null_mut()
  395. }
  396. }
  397. #[no_mangle]
  398. pub unsafe extern "C" fn mblen(s: *const c_char, n: size_t) -> c_int {
  399. let mut wc: wchar_t = 0;
  400. let mut state: mbstate_t = mbstate_t {};
  401. let result: usize = mbrtowc(&mut wc, s, n, &mut state);
  402. if result == -1isize as usize {
  403. return -1;
  404. }
  405. if result == -2isize as usize {
  406. return -1;
  407. }
  408. result as i32
  409. }
  410. #[no_mangle]
  411. pub unsafe extern "C" fn mbstowcs(pwcs: *mut wchar_t, mut s: *const c_char, n: size_t) -> size_t {
  412. let mut state: mbstate_t = mbstate_t {};
  413. mbsrtowcs(pwcs, &mut s, n, &mut state)
  414. }
  415. #[no_mangle]
  416. pub unsafe extern "C" fn mbtowc(pwc: *mut wchar_t, s: *const c_char, n: size_t) -> c_int {
  417. let mut state: mbstate_t = mbstate_t {};
  418. mbrtowc(pwc, s, n, &mut state) as c_int
  419. }
  420. fn inner_mktemp<T, F>(name: *mut c_char, suffix_len: c_int, mut attempt: F) -> Option<T>
  421. where
  422. F: FnMut() -> Option<T>,
  423. {
  424. let len = unsafe { strlen(name) as c_int };
  425. if len < 6 || suffix_len > len - 6 {
  426. unsafe { platform::errno = errno::EINVAL };
  427. return None;
  428. }
  429. for i in (len - suffix_len - 6)..(len - suffix_len) {
  430. if unsafe { *name.offset(i as isize) } != b'X' as c_char {
  431. unsafe { platform::errno = errno::EINVAL };
  432. return None;
  433. }
  434. }
  435. let mut rng = JitterRng::new_with_timer(get_nstime);
  436. let _ = rng.test_timer();
  437. for _ in 0..100 {
  438. let char_iter = iter::repeat(())
  439. .map(|()| rng.sample(Alphanumeric))
  440. .take(6)
  441. .enumerate();
  442. unsafe {
  443. for (i, c) in char_iter {
  444. *name.offset((len as isize) - (suffix_len as isize) - (i as isize) - 1) =
  445. c as c_char
  446. }
  447. }
  448. if let result @ Some(_) = attempt() {
  449. return result;
  450. }
  451. }
  452. unsafe { platform::errno = errno::EEXIST }
  453. None
  454. }
  455. #[no_mangle]
  456. pub unsafe extern "C" fn mktemp(name: *mut c_char) -> *mut c_char {
  457. if inner_mktemp(name, 0, || {
  458. let name = CStr::from_ptr(name);
  459. if Sys::access(name, 0) != 0 && platform::errno == ENOENT {
  460. Some(())
  461. } else {
  462. None
  463. }
  464. })
  465. .is_none()
  466. {
  467. *name = 0;
  468. }
  469. name
  470. }
  471. fn get_nstime() -> u64 {
  472. let mut ts: timespec = unsafe { mem::uninitialized() };
  473. Sys::clock_gettime(CLOCK_MONOTONIC, &mut ts);
  474. ts.tv_nsec as u64
  475. }
  476. #[no_mangle]
  477. pub extern "C" fn mkostemps(name: *mut c_char, suffix_len: c_int, mut flags: c_int) -> c_int {
  478. flags &= !O_ACCMODE;
  479. flags |= O_RDWR | O_CREAT | O_EXCL;
  480. inner_mktemp(name, suffix_len, || {
  481. let name = unsafe { CStr::from_ptr(name) };
  482. let fd = Sys::open(name, flags, 0o600);
  483. if fd >= 0 {
  484. Some(fd)
  485. } else {
  486. None
  487. }
  488. })
  489. .unwrap_or(-1)
  490. }
  491. #[no_mangle]
  492. pub extern "C" fn mkstemp(name: *mut c_char) -> c_int {
  493. mkostemps(name, 0, 0)
  494. }
  495. #[no_mangle]
  496. pub extern "C" fn mkostemp(name: *mut c_char, flags: c_int) -> c_int {
  497. mkostemps(name, 0, flags)
  498. }
  499. #[no_mangle]
  500. pub extern "C" fn mkstemps(name: *mut c_char, suffix_len: c_int) -> c_int {
  501. mkostemps(name, suffix_len, 0)
  502. }
  503. #[no_mangle]
  504. pub unsafe extern "C" fn mrand48() -> c_long {
  505. let new_xi = lcg48::generator_step(lcg48::DEFAULT_XI.as_mut_ptr());
  506. lcg48::int32_from_x(new_xi)
  507. }
  508. #[no_mangle]
  509. pub unsafe extern "C" fn nrand48(xsubi: *mut c_ushort) -> c_long {
  510. let new_xi = lcg48::generator_step(xsubi);
  511. lcg48::uint31_from_x(new_xi)
  512. }
  513. // #[no_mangle]
  514. pub extern "C" fn ptsname(fildes: c_int) -> *mut c_char {
  515. unimplemented!();
  516. }
  517. #[no_mangle]
  518. pub unsafe extern "C" fn putenv(insert: *mut c_char) -> c_int {
  519. assert_ne!(insert, ptr::null_mut(), "putenv(NULL)");
  520. if let Some((i, _)) = find_env(insert) {
  521. //TODO: find out why this crashes: platform::free(platform::inner_environ[i] as *mut c_void);
  522. platform::inner_environ[i] = insert;
  523. } else {
  524. let i = platform::inner_environ.len() - 1;
  525. assert_eq!(
  526. platform::inner_environ[i],
  527. ptr::null_mut(),
  528. "environ did not end with null"
  529. );
  530. platform::inner_environ[i] = insert;
  531. platform::inner_environ.push(ptr::null_mut());
  532. platform::environ = platform::inner_environ.as_mut_ptr();
  533. }
  534. 0
  535. }
  536. #[no_mangle]
  537. pub extern "C" fn qsort(
  538. base: *mut c_void,
  539. nel: size_t,
  540. width: size_t,
  541. compar: Option<extern "C" fn(*const c_void, *const c_void) -> c_int>,
  542. ) {
  543. if let Some(comp) = compar {
  544. // XXX: check width too? not specified
  545. if nel > 0 {
  546. // XXX: maybe try to do mergesort/timsort first and fallback to introsort if memory
  547. // allocation fails? not sure what is ideal
  548. sort::introsort(base as *mut c_char, nel, width, comp);
  549. }
  550. }
  551. }
  552. #[no_mangle]
  553. pub unsafe extern "C" fn rand() -> c_int {
  554. match RNG {
  555. Some(ref mut rng) => RNG_SAMPLER.sample(rng),
  556. None => {
  557. let mut rng = XorShiftRng::from_seed([1; 16]);
  558. let ret = RNG_SAMPLER.sample(&mut rng);
  559. RNG = Some(rng);
  560. ret
  561. }
  562. }
  563. }
  564. #[no_mangle]
  565. pub unsafe extern "C" fn rand_r(seed: *mut c_uint) -> c_int {
  566. if seed.is_null() {
  567. errno::EINVAL
  568. } else {
  569. // set the type explicitly so this will fail if the array size for XorShiftRng changes
  570. let seed_arr: [u8; 16] = mem::transmute([*seed; 16 / mem::size_of::<c_uint>()]);
  571. let mut rng = XorShiftRng::from_seed(seed_arr);
  572. let ret = RNG_SAMPLER.sample(&mut rng);
  573. *seed = ret as _;
  574. ret
  575. }
  576. }
  577. // #[no_mangle]
  578. pub extern "C" fn random() -> c_long {
  579. unimplemented!();
  580. }
  581. #[no_mangle]
  582. pub unsafe extern "C" fn realloc(ptr: *mut c_void, size: size_t) -> *mut c_void {
  583. let ptr = platform::realloc(ptr, size);
  584. if ptr.is_null() {
  585. platform::errno = errno::ENOMEM;
  586. }
  587. ptr
  588. }
  589. #[no_mangle]
  590. pub unsafe extern "C" fn realpath(pathname: *const c_char, resolved: *mut c_char) -> *mut c_char {
  591. let ptr = if resolved.is_null() {
  592. malloc(limits::PATH_MAX) as *mut c_char
  593. } else {
  594. resolved
  595. };
  596. let out = slice::from_raw_parts_mut(ptr as *mut u8, limits::PATH_MAX);
  597. {
  598. let file = match File::open(&CStr::from_ptr(pathname), O_PATH | O_CLOEXEC) {
  599. Ok(file) => file,
  600. Err(_) => return ptr::null_mut(),
  601. };
  602. let len = out.len();
  603. let read = Sys::fpath(*file, &mut out[..len - 1]);
  604. if read < 0 {
  605. return ptr::null_mut();
  606. }
  607. out[read as usize] = 0;
  608. }
  609. ptr
  610. }
  611. #[no_mangle]
  612. pub unsafe extern "C" fn seed48(seed16v: *mut c_ushort) -> *mut c_ushort {
  613. lcg48::reset_a_and_c();
  614. lcg48::STASHED_XI = lcg48::DEFAULT_XI;
  615. let new_xi = lcg48::uint48_from_ushort_arr3(seed16v);
  616. lcg48::set_ushort_arr3_from_uint48(lcg48::DEFAULT_XI.as_mut_ptr(), new_xi);
  617. lcg48::STASHED_XI.as_mut_ptr()
  618. }
  619. #[no_mangle]
  620. pub unsafe extern "C" fn setenv(
  621. mut key: *const c_char,
  622. mut value: *const c_char,
  623. overwrite: c_int,
  624. ) -> c_int {
  625. let mut key_len = 0;
  626. while *key.offset(key_len) != 0 {
  627. key_len += 1;
  628. }
  629. let mut value_len = 0;
  630. while *value.offset(value_len) != 0 {
  631. value_len += 1;
  632. }
  633. let index = if let Some((i, existing)) = find_env(key) {
  634. if overwrite == 0 {
  635. return 0;
  636. }
  637. let mut existing_len = 0;
  638. while *existing.offset(existing_len) != 0 {
  639. existing_len += 1;
  640. }
  641. if existing_len >= value_len {
  642. // Reuse existing element's allocation
  643. for i in 0..=value_len {
  644. *existing.offset(i) = *value.offset(i);
  645. }
  646. return 0;
  647. } else {
  648. i
  649. }
  650. } else {
  651. let i = platform::inner_environ.len() - 1;
  652. assert_eq!(
  653. platform::inner_environ[i],
  654. ptr::null_mut(),
  655. "environ did not end with null"
  656. );
  657. platform::inner_environ.push(ptr::null_mut());
  658. platform::environ = platform::inner_environ.as_mut_ptr();
  659. i
  660. };
  661. //platform::free(platform::inner_environ[index] as *mut c_void);
  662. let mut ptr = platform::alloc(key_len as usize + 1 + value_len as usize) as *mut c_char;
  663. platform::inner_environ[index] = ptr;
  664. while *key != 0 {
  665. *ptr = *key;
  666. ptr = ptr.offset(1);
  667. key = key.offset(1);
  668. }
  669. *ptr = b'=' as c_char;
  670. ptr = ptr.offset(1);
  671. while *value != 0 {
  672. *ptr = *value;
  673. ptr = ptr.offset(1);
  674. value = value.offset(1);
  675. }
  676. *ptr = 0;
  677. 0
  678. }
  679. // #[no_mangle]
  680. pub extern "C" fn setkey(key: *const c_char) {
  681. unimplemented!();
  682. }
  683. // #[no_mangle]
  684. pub extern "C" fn setstate(state: *const c_char) -> *mut c_char {
  685. unimplemented!();
  686. }
  687. #[no_mangle]
  688. pub unsafe extern "C" fn srand(seed: c_uint) {
  689. RNG = Some(XorShiftRng::from_seed([seed as u8; 16]));
  690. }
  691. #[no_mangle]
  692. pub unsafe extern "C" fn srand48(seedval: c_long) {
  693. lcg48::reset_a_and_c();
  694. /* Set the high 32 bits of the 48-bit X_i value to the lower 32 bits
  695. * of the input argument, and the lower 16 bits to 0x330e, as
  696. * specified in POSIX. */
  697. let new_xi = (((seedval as u32) as u64) << 16) | 0x330e_u64;
  698. lcg48::set_ushort_arr3_from_uint48(lcg48::DEFAULT_XI.as_mut_ptr(), new_xi);
  699. }
  700. // #[no_mangle]
  701. pub extern "C" fn srandom(seed: c_uint) {
  702. unimplemented!();
  703. }
  704. #[no_mangle]
  705. pub unsafe extern "C" fn strtod(s: *const c_char, endptr: *mut *mut c_char) -> c_double {
  706. strto_float_impl!(c_double, s, endptr)
  707. }
  708. #[no_mangle]
  709. pub unsafe extern "C" fn strtof(s: *const c_char, endptr: *mut *mut c_char) -> c_float {
  710. strto_float_impl!(c_float, s, endptr)
  711. }
  712. pub fn is_positive(ch: c_char) -> Option<(bool, isize)> {
  713. match ch {
  714. 0 => None,
  715. ch if ch == b'+' as c_char => Some((true, 1)),
  716. ch if ch == b'-' as c_char => Some((false, 1)),
  717. _ => Some((true, 0)),
  718. }
  719. }
  720. pub unsafe fn detect_base(s: *const c_char) -> Option<(c_int, isize)> {
  721. let first = *s as u8;
  722. match first {
  723. 0 => None,
  724. b'0' => {
  725. let second = *s.offset(1) as u8;
  726. if second == b'X' || second == b'x' {
  727. Some((16, 2))
  728. } else if second >= b'0' && second <= b'7' {
  729. Some((8, 1))
  730. } else {
  731. // in this case, the prefix (0) is going to be the number
  732. Some((8, 0))
  733. }
  734. }
  735. _ => Some((10, 0)),
  736. }
  737. }
  738. pub unsafe fn convert_octal(s: *const c_char) -> Option<(c_ulong, isize, bool)> {
  739. if *s != 0 && *s == b'0' as c_char {
  740. if let Some((val, idx, overflow)) = convert_integer(s.offset(1), 8) {
  741. Some((val, idx + 1, overflow))
  742. } else {
  743. // in case the prefix is not actually a prefix
  744. Some((0, 1, false))
  745. }
  746. } else {
  747. None
  748. }
  749. }
  750. pub unsafe fn convert_hex(s: *const c_char) -> Option<(c_ulong, isize, bool)> {
  751. if (*s != 0 && *s == b'0' as c_char)
  752. && (*s.offset(1) != 0 && (*s.offset(1) == b'x' as c_char || *s.offset(1) == b'X' as c_char))
  753. {
  754. convert_integer(s.offset(2), 16).map(|(val, idx, overflow)| (val, idx + 2, overflow))
  755. } else {
  756. convert_integer(s, 16).map(|(val, idx, overflow)| (val, idx, overflow))
  757. }
  758. }
  759. pub unsafe fn convert_integer(s: *const c_char, base: c_int) -> Option<(c_ulong, isize, bool)> {
  760. // -1 means the character is invalid
  761. #[rustfmt::skip]
  762. const LOOKUP_TABLE: [c_long; 256] = [
  763. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  764. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  765. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  766. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
  767. -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
  768. 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
  769. -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
  770. 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
  771. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  772. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  773. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  774. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  775. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  776. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  777. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  778. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  779. ];
  780. let mut num: c_ulong = 0;
  781. let mut idx = 0;
  782. let mut overflowed = false;
  783. loop {
  784. // `-1 as usize` is usize::MAX
  785. // `-1 as u8 as usize` is u8::MAX
  786. // It extends by the sign bit unless we cast it to unsigned first.
  787. let val = LOOKUP_TABLE[*s.offset(idx) as u8 as usize];
  788. if val == -1 || val as c_int >= base {
  789. break;
  790. } else {
  791. if let Some(res) = num
  792. .checked_mul(base as c_ulong)
  793. .and_then(|num| num.checked_add(val as c_ulong))
  794. {
  795. num = res;
  796. } else {
  797. platform::errno = ERANGE;
  798. num = c_ulong::max_value();
  799. overflowed = true;
  800. }
  801. idx += 1;
  802. }
  803. }
  804. if idx > 0 {
  805. Some((num, idx, overflowed))
  806. } else {
  807. None
  808. }
  809. }
  810. #[no_mangle]
  811. pub unsafe extern "C" fn strtoul(
  812. s: *const c_char,
  813. endptr: *mut *mut c_char,
  814. base: c_int,
  815. ) -> c_ulong {
  816. strto_impl!(
  817. c_ulong,
  818. false,
  819. c_ulong::max_value(),
  820. c_ulong::min_value(),
  821. s,
  822. endptr,
  823. base
  824. )
  825. }
  826. #[no_mangle]
  827. pub unsafe extern "C" fn strtol(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_long {
  828. strto_impl!(
  829. c_long,
  830. true,
  831. c_long::max_value(),
  832. c_long::min_value(),
  833. s,
  834. endptr,
  835. base
  836. )
  837. }
  838. #[no_mangle]
  839. pub unsafe extern "C" fn strtoull(
  840. s: *const c_char,
  841. endptr: *mut *mut c_char,
  842. base: c_int,
  843. ) -> c_ulonglong {
  844. strtoul(s, endptr, base)
  845. }
  846. #[no_mangle]
  847. pub unsafe extern "C" fn strtoll(
  848. s: *const c_char,
  849. endptr: *mut *mut c_char,
  850. base: c_int,
  851. ) -> c_longlong {
  852. strtol(s, endptr, base)
  853. }
  854. #[no_mangle]
  855. pub unsafe extern "C" fn system(command: *const c_char) -> c_int {
  856. //TODO: share code with popen
  857. let child_pid = unistd::fork();
  858. if child_pid == 0 {
  859. let command_nonnull = if command.is_null() {
  860. "exit 0\0".as_ptr()
  861. } else {
  862. command as *const u8
  863. };
  864. let shell = "/bin/sh\0".as_ptr();
  865. let args = [
  866. "sh\0".as_ptr(),
  867. "-c\0".as_ptr(),
  868. command_nonnull,
  869. ptr::null(),
  870. ];
  871. unistd::execv(shell as *const c_char, args.as_ptr() as *const *mut c_char);
  872. exit(127);
  873. unreachable!();
  874. } else if child_pid > 0 {
  875. let mut wstatus = 0;
  876. if Sys::waitpid(child_pid, &mut wstatus, 0) == !0 {
  877. return -1;
  878. }
  879. wstatus
  880. } else {
  881. -1
  882. }
  883. }
  884. // #[no_mangle]
  885. pub extern "C" fn ttyslot() -> c_int {
  886. unimplemented!();
  887. }
  888. // #[no_mangle]
  889. pub extern "C" fn unlockpt(fildes: c_int) -> c_int {
  890. unimplemented!();
  891. }
  892. #[no_mangle]
  893. pub unsafe extern "C" fn unsetenv(key: *const c_char) -> c_int {
  894. if let Some((i, _)) = find_env(key) {
  895. // No need to worry about updating the pointer, this does not
  896. // reallocate in any way. And the final null is already shifted back.
  897. platform::inner_environ.remove(i);
  898. }
  899. 0
  900. }
  901. #[no_mangle]
  902. pub unsafe extern "C" fn valloc(size: size_t) -> *mut c_void {
  903. /* sysconf(_SC_PAGESIZE) is a c_long and may in principle not
  904. * convert correctly to a size_t. */
  905. match size_t::try_from(sysconf(_SC_PAGESIZE)) {
  906. Ok(page_size) => {
  907. /* valloc() is not supposed to be able to set errno to
  908. * EINVAL, hence no call to memalign(). */
  909. let ptr = platform::alloc_align(size, page_size);
  910. if ptr.is_null() {
  911. platform::errno = errno::ENOMEM;
  912. }
  913. ptr
  914. }
  915. Err(_) => {
  916. // A corner case. No errno setting.
  917. ptr::null_mut()
  918. }
  919. }
  920. }
  921. #[no_mangle]
  922. pub extern "C" fn wcstombs(s: *mut c_char, pwcs: *mut *const wchar_t, n: size_t) -> size_t {
  923. let mut state: mbstate_t = mbstate_t {};
  924. wcsrtombs(s, pwcs, n, &mut state)
  925. }
  926. #[no_mangle]
  927. pub unsafe extern "C" fn wctomb(s: *mut c_char, wc: wchar_t) -> c_int {
  928. let mut state: mbstate_t = mbstate_t {};
  929. let result: usize = wcrtomb(s, wc, &mut state);
  930. if result == -1isize as usize {
  931. return -1;
  932. }
  933. if result == -2isize as usize {
  934. return -1;
  935. }
  936. result as c_int
  937. }