mod.rs 24 KB

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