mod.rs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  1. //! unistd implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/unistd.h.html
  2. use core::{mem, ptr, slice};
  3. use c_str::CStr;
  4. use header::errno;
  5. use header::limits;
  6. use header::stdlib::getenv;
  7. use header::sys_ioctl;
  8. use header::sys_time;
  9. use header::termios;
  10. use header::time::timespec;
  11. use platform;
  12. use platform::types::*;
  13. use platform::{Pal, Sys};
  14. pub use self::brk::*;
  15. pub use self::getopt::*;
  16. pub use self::pathconf::*;
  17. pub use self::sysconf::*;
  18. mod brk;
  19. mod getopt;
  20. mod pathconf;
  21. mod sysconf;
  22. pub const F_OK: c_int = 0;
  23. pub const R_OK: c_int = 4;
  24. pub const W_OK: c_int = 2;
  25. pub const X_OK: c_int = 1;
  26. pub const SEEK_SET: c_int = 0;
  27. pub const SEEK_CUR: c_int = 1;
  28. pub const SEEK_END: c_int = 2;
  29. pub const F_ULOCK: c_int = 0;
  30. pub const F_LOCK: c_int = 1;
  31. pub const F_TLOCK: c_int = 2;
  32. pub const F_TEST: c_int = 3;
  33. pub const STDIN_FILENO: c_int = 0;
  34. pub const STDOUT_FILENO: c_int = 1;
  35. pub const STDERR_FILENO: c_int = 2;
  36. #[no_mangle]
  37. pub extern "C" fn _exit(status: c_int) {
  38. Sys::exit(status)
  39. }
  40. #[no_mangle]
  41. pub unsafe extern "C" fn access(path: *const c_char, mode: c_int) -> c_int {
  42. let path = CStr::from_ptr(path);
  43. Sys::access(path, mode)
  44. }
  45. #[no_mangle]
  46. pub extern "C" fn alarm(seconds: c_uint) -> c_uint {
  47. let mut timer = sys_time::itimerval {
  48. it_value: sys_time::timeval {
  49. tv_sec: seconds as time_t,
  50. tv_usec: 0,
  51. },
  52. ..Default::default()
  53. };
  54. let errno_backup = unsafe { platform::errno };
  55. let secs = if sys_time::setitimer(sys_time::ITIMER_REAL, &timer, &mut timer) < 0 {
  56. 0
  57. } else {
  58. timer.it_value.tv_sec as c_uint + if timer.it_value.tv_usec > 0 { 1 } else { 0 }
  59. };
  60. unsafe {
  61. platform::errno = errno_backup;
  62. }
  63. secs
  64. }
  65. #[no_mangle]
  66. pub unsafe extern "C" fn chdir(path: *const c_char) -> c_int {
  67. let path = CStr::from_ptr(path);
  68. Sys::chdir(path)
  69. }
  70. // #[no_mangle]
  71. pub extern "C" fn chroot(path: *const c_char) -> c_int {
  72. unimplemented!();
  73. }
  74. #[no_mangle]
  75. pub unsafe extern "C" fn chown(path: *const c_char, owner: uid_t, group: gid_t) -> c_int {
  76. let path = CStr::from_ptr(path);
  77. Sys::chown(path, owner, group)
  78. }
  79. #[no_mangle]
  80. pub extern "C" fn close(fildes: c_int) -> c_int {
  81. Sys::close(fildes)
  82. }
  83. // #[no_mangle]
  84. pub extern "C" fn confstr(name: c_int, buf: *mut c_char, len: size_t) -> size_t {
  85. unimplemented!();
  86. }
  87. // #[no_mangle]
  88. pub extern "C" fn crypt(key: *const c_char, salt: *const c_char) -> *mut c_char {
  89. unimplemented!();
  90. }
  91. #[no_mangle]
  92. pub extern "C" fn dup(fildes: c_int) -> c_int {
  93. Sys::dup(fildes)
  94. }
  95. #[no_mangle]
  96. pub extern "C" fn dup2(fildes: c_int, fildes2: c_int) -> c_int {
  97. Sys::dup2(fildes, fildes2)
  98. }
  99. // #[no_mangle]
  100. pub extern "C" fn encrypt(block: [c_char; 64], edflag: c_int) {
  101. unimplemented!();
  102. }
  103. // #[no_mangle]
  104. // pub extern "C" fn execl(path: *const c_char, args: *const *mut c_char) -> c_int {
  105. // unimplemented!();
  106. // }
  107. // #[no_mangle]
  108. // pub extern "C" fn execle(
  109. // path: *const c_char,
  110. // args: *const *mut c_char,
  111. // envp: *const *mut c_char,
  112. // ) -> c_int {
  113. // unimplemented!();
  114. // }
  115. // #[no_mangle]
  116. // pub extern "C" fn execlp(file: *const c_char, args: *const *mut c_char) -> c_int {
  117. // unimplemented!();
  118. // }
  119. #[no_mangle]
  120. pub unsafe extern "C" fn execv(path: *const c_char, argv: *const *mut c_char) -> c_int {
  121. execve(path, argv, platform::environ)
  122. }
  123. #[no_mangle]
  124. pub unsafe extern "C" fn execve(
  125. path: *const c_char,
  126. argv: *const *mut c_char,
  127. envp: *const *mut c_char,
  128. ) -> c_int {
  129. let path = CStr::from_ptr(path);
  130. Sys::execve(path, argv, envp)
  131. }
  132. #[cfg(target_os = "linux")]
  133. const PATH_SEPARATOR: u8 = b':';
  134. #[cfg(target_os = "redox")]
  135. const PATH_SEPARATOR: u8 = b';';
  136. #[no_mangle]
  137. pub unsafe extern "C" fn execvp(file: *const c_char, argv: *const *mut c_char) -> c_int {
  138. let file = CStr::from_ptr(file);
  139. if file.to_bytes().contains(&b'/')
  140. || (cfg!(target_os = "redox") && file.to_bytes().contains(&b':'))
  141. {
  142. execv(file.as_ptr(), argv)
  143. } else {
  144. let mut error = errno::ENOENT;
  145. let path_env = getenv(c_str!("PATH\0").as_ptr());
  146. if !path_env.is_null() {
  147. let path_env = CStr::from_ptr(path_env);
  148. for mut path in path_env.to_bytes().split(|&b| b == PATH_SEPARATOR) {
  149. let mut program = path.to_vec();
  150. program.push(b'/');
  151. program.extend_from_slice(file.to_bytes());
  152. program.push(b'\0');
  153. let program_c = CStr::from_bytes_with_nul(&program).unwrap();
  154. execv(program_c.as_ptr(), argv);
  155. match platform::errno {
  156. errno::ENOENT => (),
  157. other => error = other,
  158. }
  159. }
  160. }
  161. platform::errno = error;
  162. -1
  163. }
  164. }
  165. #[no_mangle]
  166. pub extern "C" fn fchown(fildes: c_int, owner: uid_t, group: gid_t) -> c_int {
  167. Sys::fchown(fildes, owner, group)
  168. }
  169. #[no_mangle]
  170. pub extern "C" fn fchdir(fildes: c_int) -> c_int {
  171. Sys::fchdir(fildes)
  172. }
  173. // #[no_mangle]
  174. pub extern "C" fn fdatasync(fildes: c_int) -> c_int {
  175. unimplemented!();
  176. }
  177. #[no_mangle]
  178. pub extern "C" fn fork() -> pid_t {
  179. Sys::fork()
  180. }
  181. #[no_mangle]
  182. pub extern "C" fn fsync(fildes: c_int) -> c_int {
  183. Sys::fsync(fildes)
  184. }
  185. #[no_mangle]
  186. pub extern "C" fn ftruncate(fildes: c_int, length: off_t) -> c_int {
  187. Sys::ftruncate(fildes, length)
  188. }
  189. #[no_mangle]
  190. pub extern "C" fn getcwd(mut buf: *mut c_char, mut size: size_t) -> *mut c_char {
  191. let alloc = buf.is_null();
  192. let mut stack_buf = [0; limits::PATH_MAX];
  193. if alloc {
  194. buf = stack_buf.as_mut_ptr();
  195. size = stack_buf.len();
  196. }
  197. let ret = Sys::getcwd(buf, size);
  198. if ret.is_null() {
  199. return ptr::null_mut();
  200. }
  201. if alloc {
  202. let len = stack_buf
  203. .iter()
  204. .position(|b| *b == 0)
  205. .expect("no nul-byte in getcwd string")
  206. + 1;
  207. let heap_buf = unsafe { platform::alloc(len) as *mut c_char };
  208. for i in 0..len {
  209. unsafe {
  210. *heap_buf.add(i) = stack_buf[i];
  211. }
  212. }
  213. heap_buf
  214. } else {
  215. ret
  216. }
  217. }
  218. // #[no_mangle]
  219. pub extern "C" fn getdtablesize() -> c_int {
  220. unimplemented!();
  221. }
  222. #[no_mangle]
  223. pub extern "C" fn getegid() -> gid_t {
  224. Sys::getegid()
  225. }
  226. #[no_mangle]
  227. pub extern "C" fn geteuid() -> uid_t {
  228. Sys::geteuid()
  229. }
  230. #[no_mangle]
  231. pub extern "C" fn getgid() -> gid_t {
  232. Sys::getgid()
  233. }
  234. // #[no_mangle]
  235. pub extern "C" fn getgroups(gidsetsize: c_int, grouplist: *mut gid_t) -> c_int {
  236. unimplemented!();
  237. }
  238. // #[no_mangle]
  239. pub extern "C" fn gethostid() -> c_long {
  240. unimplemented!();
  241. }
  242. #[no_mangle]
  243. pub unsafe extern "C" fn gethostname(mut name: *mut c_char, mut len: size_t) -> c_int {
  244. let mut uts = mem::uninitialized();
  245. let err = Sys::uname(&mut uts);
  246. if err < 0 {
  247. mem::forget(uts);
  248. return err;
  249. }
  250. for c in uts.nodename.iter() {
  251. if len == 0 {
  252. break;
  253. }
  254. len -= 1;
  255. *name = *c;
  256. if *name == 0 {
  257. // We do want to copy the zero also, so we check this after the copying.
  258. break;
  259. }
  260. name = name.offset(1);
  261. }
  262. 0
  263. }
  264. #[no_mangle]
  265. pub unsafe extern "C" fn getlogin() -> *mut c_char {
  266. static mut LOGIN: [c_char; 256] = [0; 256];
  267. if getlogin_r(LOGIN.as_mut_ptr(), LOGIN.len()) == 0 {
  268. LOGIN.as_mut_ptr()
  269. } else {
  270. ptr::null_mut()
  271. }
  272. }
  273. #[no_mangle]
  274. pub extern "C" fn getlogin_r(name: *mut c_char, namesize: size_t) -> c_int {
  275. //TODO: Determine correct getlogin result on Redox
  276. unsafe { platform::errno = errno::ENOENT };
  277. -1
  278. }
  279. #[no_mangle]
  280. pub extern "C" fn getpagesize() -> c_int {
  281. sysconf(_SC_PAGESIZE) as c_int
  282. }
  283. // #[no_mangle]
  284. pub extern "C" fn getpass(prompt: *const c_char) -> *mut c_char {
  285. unimplemented!();
  286. }
  287. #[no_mangle]
  288. pub extern "C" fn getpgid(pid: pid_t) -> pid_t {
  289. Sys::getpgid(pid)
  290. }
  291. #[no_mangle]
  292. pub extern "C" fn getpgrp() -> pid_t {
  293. Sys::getpgid(Sys::getpid())
  294. }
  295. #[no_mangle]
  296. pub extern "C" fn getpid() -> pid_t {
  297. Sys::getpid()
  298. }
  299. #[no_mangle]
  300. pub extern "C" fn getppid() -> pid_t {
  301. Sys::getppid()
  302. }
  303. // #[no_mangle]
  304. pub extern "C" fn getsid(pid: pid_t) -> pid_t {
  305. unimplemented!();
  306. }
  307. #[no_mangle]
  308. pub extern "C" fn getuid() -> uid_t {
  309. Sys::getuid()
  310. }
  311. #[no_mangle]
  312. pub extern "C" fn getwd(path_name: *mut c_char) -> *mut c_char {
  313. getcwd(path_name, limits::PATH_MAX)
  314. }
  315. #[no_mangle]
  316. pub extern "C" fn isatty(fd: c_int) -> c_int {
  317. let mut t = termios::termios::default();
  318. if unsafe { termios::tcgetattr(fd, &mut t as *mut termios::termios) == 0 } {
  319. 1
  320. } else {
  321. 0
  322. }
  323. }
  324. // #[no_mangle]
  325. pub extern "C" fn lchown(path: *const c_char, owner: uid_t, group: gid_t) -> c_int {
  326. unimplemented!();
  327. }
  328. #[no_mangle]
  329. pub unsafe extern "C" fn link(path1: *const c_char, path2: *const c_char) -> c_int {
  330. let path1 = CStr::from_ptr(path1);
  331. let path2 = CStr::from_ptr(path2);
  332. Sys::link(path1, path2)
  333. }
  334. // #[no_mangle]
  335. pub extern "C" fn lockf(fildes: c_int, function: c_int, size: off_t) -> c_int {
  336. unimplemented!();
  337. }
  338. #[no_mangle]
  339. pub extern "C" fn lseek(fildes: c_int, offset: off_t, whence: c_int) -> off_t {
  340. Sys::lseek(fildes, offset, whence)
  341. }
  342. // #[no_mangle]
  343. pub extern "C" fn nice(incr: c_int) -> c_int {
  344. unimplemented!();
  345. }
  346. // #[no_mangle]
  347. pub extern "C" fn pause() -> c_int {
  348. unimplemented!();
  349. }
  350. #[no_mangle]
  351. pub unsafe extern "C" fn pipe(fildes: *mut c_int) -> c_int {
  352. Sys::pipe(slice::from_raw_parts_mut(fildes, 2))
  353. }
  354. #[no_mangle]
  355. pub extern "C" fn pread(fildes: c_int, buf: *mut c_void, nbyte: size_t, offset: off_t) -> ssize_t {
  356. //TODO: better pread using system calls
  357. let previous = lseek(fildes, offset, SEEK_SET);
  358. if previous == -1 {
  359. return -1;
  360. }
  361. let res = read(fildes, buf, nbyte);
  362. if res < 0 {
  363. return res;
  364. }
  365. if lseek(fildes, previous, SEEK_SET) == -1 {
  366. return -1;
  367. }
  368. res
  369. }
  370. // #[no_mangle]
  371. pub extern "C" fn pthread_atfork(
  372. prepare: Option<extern "C" fn()>,
  373. parent: Option<extern "C" fn()>,
  374. child: Option<extern "C" fn()>,
  375. ) -> c_int {
  376. unimplemented!();
  377. }
  378. #[no_mangle]
  379. pub extern "C" fn pwrite(
  380. fildes: c_int,
  381. buf: *const c_void,
  382. nbyte: size_t,
  383. offset: off_t,
  384. ) -> ssize_t {
  385. //TODO: better pwrite using system calls
  386. let previous = lseek(fildes, offset, SEEK_SET);
  387. if previous == -1 {
  388. return -1;
  389. }
  390. let res = write(fildes, buf, nbyte);
  391. if res < 0 {
  392. return res;
  393. }
  394. if lseek(fildes, previous, SEEK_SET) == -1 {
  395. return -1;
  396. }
  397. res
  398. }
  399. #[no_mangle]
  400. pub extern "C" fn read(fildes: c_int, buf: *const c_void, nbyte: size_t) -> ssize_t {
  401. let buf = unsafe { slice::from_raw_parts_mut(buf as *mut u8, nbyte as usize) };
  402. trace_expr!(
  403. Sys::read(fildes, buf),
  404. "read({}, {:p}, {})",
  405. fildes,
  406. buf,
  407. nbyte
  408. )
  409. }
  410. #[no_mangle]
  411. pub unsafe extern "C" fn readlink(
  412. path: *const c_char,
  413. buf: *mut c_char,
  414. bufsize: size_t,
  415. ) -> ssize_t {
  416. let path = CStr::from_ptr(path);
  417. let buf = slice::from_raw_parts_mut(buf as *mut u8, bufsize as usize);
  418. Sys::readlink(path, buf)
  419. }
  420. #[no_mangle]
  421. pub unsafe extern "C" fn rmdir(path: *const c_char) -> c_int {
  422. let path = CStr::from_ptr(path);
  423. Sys::rmdir(path)
  424. }
  425. #[no_mangle]
  426. pub extern "C" fn setgid(gid: gid_t) -> c_int {
  427. Sys::setregid(gid, gid)
  428. }
  429. #[no_mangle]
  430. pub extern "C" fn setpgid(pid: pid_t, pgid: pid_t) -> c_int {
  431. Sys::setpgid(pid, pgid)
  432. }
  433. #[no_mangle]
  434. pub extern "C" fn setpgrp() -> pid_t {
  435. setpgid(0, 0)
  436. }
  437. #[no_mangle]
  438. pub extern "C" fn setregid(rgid: gid_t, egid: gid_t) -> c_int {
  439. Sys::setregid(rgid, egid)
  440. }
  441. #[no_mangle]
  442. pub extern "C" fn setreuid(ruid: uid_t, euid: uid_t) -> c_int {
  443. Sys::setreuid(ruid, euid)
  444. }
  445. // #[no_mangle]
  446. pub extern "C" fn setsid() -> pid_t {
  447. unimplemented!();
  448. }
  449. #[no_mangle]
  450. pub extern "C" fn setuid(uid: uid_t) -> c_int {
  451. Sys::setreuid(uid, uid)
  452. }
  453. #[no_mangle]
  454. pub extern "C" fn sleep(seconds: c_uint) -> c_uint {
  455. let rqtp = timespec {
  456. tv_sec: seconds as i64,
  457. tv_nsec: 0,
  458. };
  459. let rmtp = ptr::null_mut();
  460. Sys::nanosleep(&rqtp, rmtp);
  461. 0
  462. }
  463. // #[no_mangle]
  464. pub extern "C" fn swab(src: *const c_void, dest: *mut c_void, nbytes: ssize_t) {
  465. unimplemented!();
  466. }
  467. #[no_mangle]
  468. pub unsafe extern "C" fn symlink(path1: *const c_char, path2: *const c_char) -> c_int {
  469. let path1 = CStr::from_ptr(path1);
  470. let path2 = CStr::from_ptr(path2);
  471. Sys::symlink(path1, path2)
  472. }
  473. // #[no_mangle]
  474. pub extern "C" fn sync() {
  475. unimplemented!();
  476. }
  477. #[no_mangle]
  478. pub extern "C" fn tcgetpgrp(fd: c_int) -> pid_t {
  479. let mut pgrp = 0;
  480. if unsafe { sys_ioctl::ioctl(fd, sys_ioctl::TIOCGPGRP, &mut pgrp as *mut pid_t as _) } < 0 {
  481. return -1;
  482. }
  483. pgrp
  484. }
  485. #[no_mangle]
  486. pub extern "C" fn tcsetpgrp(fd: c_int, pgrp: pid_t) -> c_int {
  487. if unsafe { sys_ioctl::ioctl(fd, sys_ioctl::TIOCSPGRP, &pgrp as *const pid_t as _) } < 0 {
  488. return -1;
  489. }
  490. pgrp
  491. }
  492. // #[no_mangle]
  493. pub extern "C" fn truncate(path: *const c_char, length: off_t) -> c_int {
  494. unimplemented!();
  495. }
  496. // #[no_mangle]
  497. pub extern "C" fn ttyname(fildes: c_int) -> *mut c_char {
  498. unimplemented!();
  499. }
  500. // #[no_mangle]
  501. pub extern "C" fn ttyname_r(fildes: c_int, name: *mut c_char, namesize: size_t) -> c_int {
  502. unimplemented!();
  503. }
  504. #[no_mangle]
  505. pub extern "C" fn ualarm(usecs: useconds_t, interval: useconds_t) -> useconds_t {
  506. let mut timer = sys_time::itimerval {
  507. it_value: sys_time::timeval {
  508. tv_sec: 0,
  509. tv_usec: usecs as suseconds_t,
  510. },
  511. it_interval: sys_time::timeval {
  512. tv_sec: 0,
  513. tv_usec: interval as suseconds_t,
  514. },
  515. };
  516. let errno_backup = unsafe { platform::errno };
  517. let ret = if sys_time::setitimer(sys_time::ITIMER_REAL, &timer, &mut timer) < 0 {
  518. 0
  519. } else {
  520. timer.it_value.tv_sec as useconds_t * 1_000_000 + timer.it_value.tv_usec as useconds_t
  521. };
  522. unsafe {
  523. platform::errno = errno_backup;
  524. }
  525. ret
  526. }
  527. #[no_mangle]
  528. pub unsafe extern "C" fn unlink(path: *const c_char) -> c_int {
  529. let path = CStr::from_ptr(path);
  530. Sys::unlink(path)
  531. }
  532. #[no_mangle]
  533. pub extern "C" fn usleep(useconds: useconds_t) -> c_int {
  534. let rqtp = timespec {
  535. tv_sec: (useconds / 1_000_000) as i64,
  536. tv_nsec: ((useconds % 1000) * 1000) as i64,
  537. };
  538. let rmtp = ptr::null_mut();
  539. Sys::nanosleep(&rqtp, rmtp)
  540. }
  541. // #[no_mangle]
  542. pub extern "C" fn vfork() -> pid_t {
  543. unimplemented!();
  544. }
  545. #[no_mangle]
  546. pub extern "C" fn write(fildes: c_int, buf: *const c_void, nbyte: size_t) -> ssize_t {
  547. use core::slice;
  548. let buf = unsafe { slice::from_raw_parts(buf as *const u8, nbyte as usize) };
  549. Sys::write(fildes, buf)
  550. }