2
0

mod.rs 24 KB

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