123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741 |
- //! unistd implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/unistd.h.html
- use core::convert::TryFrom;
- use core::{mem, ptr, slice};
- use alloc::collections::LinkedList;
- use crate::c_str::CStr;
- use crate::header::errno;
- use crate::header::limits;
- use crate::header::stdlib::getenv;
- use crate::header::sys_ioctl;
- use crate::header::sys_time;
- use crate::header::termios;
- use crate::header::time::timespec;
- use crate::platform;
- use crate::platform::types::*;
- use crate::platform::{Pal, Sys};
- pub use self::brk::*;
- pub use self::getopt::*;
- pub use self::pathconf::*;
- pub use self::sysconf::*;
- mod brk;
- mod getopt;
- mod pathconf;
- mod sysconf;
- pub const F_OK: c_int = 0;
- pub const R_OK: c_int = 4;
- pub const W_OK: c_int = 2;
- pub const X_OK: c_int = 1;
- pub const SEEK_SET: c_int = 0;
- pub const SEEK_CUR: c_int = 1;
- pub const SEEK_END: c_int = 2;
- pub const F_ULOCK: c_int = 0;
- pub const F_LOCK: c_int = 1;
- pub const F_TLOCK: c_int = 2;
- pub const F_TEST: c_int = 3;
- pub const STDIN_FILENO: c_int = 0;
- pub const STDOUT_FILENO: c_int = 1;
- pub const STDERR_FILENO: c_int = 2;
- #[thread_local]
- pub static mut fork_hooks_static: Option<[LinkedList<extern "C" fn()>; 3]> = None;
- unsafe fn init_fork_hooks<'a>() -> &'a mut [LinkedList<extern "C" fn()>; 3] {
- // Transmute the lifetime so we can return here. Should be safe as
- // long as one does not access the original fork_hooks.
- mem::transmute(
- fork_hooks_static
- .get_or_insert_with(|| [LinkedList::new(), LinkedList::new(), LinkedList::new()]),
- )
- }
- #[no_mangle]
- pub extern "C" fn _exit(status: c_int) {
- Sys::exit(status)
- }
- #[no_mangle]
- pub unsafe extern "C" fn access(path: *const c_char, mode: c_int) -> c_int {
- let path = CStr::from_ptr(path);
- Sys::access(path, mode)
- }
- #[no_mangle]
- pub extern "C" fn alarm(seconds: c_uint) -> c_uint {
- let mut timer = sys_time::itimerval {
- it_value: sys_time::timeval {
- tv_sec: seconds as time_t,
- tv_usec: 0,
- },
- ..Default::default()
- };
- let errno_backup = unsafe { platform::errno };
- let secs = if sys_time::setitimer(sys_time::ITIMER_REAL, &timer, &mut timer) < 0 {
- 0
- } else {
- timer.it_value.tv_sec as c_uint + if timer.it_value.tv_usec > 0 { 1 } else { 0 }
- };
- unsafe {
- platform::errno = errno_backup;
- }
- secs
- }
- #[no_mangle]
- pub unsafe extern "C" fn chdir(path: *const c_char) -> c_int {
- let path = CStr::from_ptr(path);
- Sys::chdir(path)
- }
- // #[no_mangle]
- pub extern "C" fn chroot(path: *const c_char) -> c_int {
- unimplemented!();
- }
- #[no_mangle]
- pub unsafe extern "C" fn chown(path: *const c_char, owner: uid_t, group: gid_t) -> c_int {
- let path = CStr::from_ptr(path);
- Sys::chown(path, owner, group)
- }
- #[no_mangle]
- pub extern "C" fn close(fildes: c_int) -> c_int {
- Sys::close(fildes)
- }
- // #[no_mangle]
- pub extern "C" fn confstr(name: c_int, buf: *mut c_char, len: size_t) -> size_t {
- unimplemented!();
- }
- // #[no_mangle]
- pub extern "C" fn crypt(key: *const c_char, salt: *const c_char) -> *mut c_char {
- unimplemented!();
- }
- #[no_mangle]
- pub extern "C" fn dup(fildes: c_int) -> c_int {
- Sys::dup(fildes)
- }
- #[no_mangle]
- pub extern "C" fn dup2(fildes: c_int, fildes2: c_int) -> c_int {
- Sys::dup2(fildes, fildes2)
- }
- // #[no_mangle]
- pub extern "C" fn encrypt(block: [c_char; 64], edflag: c_int) {
- unimplemented!();
- }
- // #[no_mangle]
- // pub extern "C" fn execl(path: *const c_char, args: *const *mut c_char) -> c_int {
- // unimplemented!();
- // }
- // #[no_mangle]
- // pub extern "C" fn execle(
- // path: *const c_char,
- // args: *const *mut c_char,
- // envp: *const *mut c_char,
- // ) -> c_int {
- // unimplemented!();
- // }
- // #[no_mangle]
- // pub extern "C" fn execlp(file: *const c_char, args: *const *mut c_char) -> c_int {
- // unimplemented!();
- // }
- #[no_mangle]
- pub unsafe extern "C" fn execv(path: *const c_char, argv: *const *mut c_char) -> c_int {
- execve(path, argv, platform::environ)
- }
- #[no_mangle]
- pub unsafe extern "C" fn execve(
- path: *const c_char,
- argv: *const *mut c_char,
- envp: *const *mut c_char,
- ) -> c_int {
- let path = CStr::from_ptr(path);
- Sys::execve(path, argv, envp)
- }
- #[cfg(target_os = "linux")]
- const PATH_SEPARATOR: u8 = b':';
- #[cfg(target_os = "redox")]
- const PATH_SEPARATOR: u8 = b';';
- #[no_mangle]
- pub unsafe extern "C" fn execvp(file: *const c_char, argv: *const *mut c_char) -> c_int {
- let file = CStr::from_ptr(file);
- if file.to_bytes().contains(&b'/')
- || (cfg!(target_os = "redox") && file.to_bytes().contains(&b':'))
- {
- execv(file.as_ptr(), argv)
- } else {
- let mut error = errno::ENOENT;
- let path_env = getenv(c_str!("PATH\0").as_ptr());
- if !path_env.is_null() {
- let path_env = CStr::from_ptr(path_env);
- for path in path_env.to_bytes().split(|&b| b == PATH_SEPARATOR) {
- let mut program = path.to_vec();
- program.push(b'/');
- program.extend_from_slice(file.to_bytes());
- program.push(b'\0');
- let program_c = CStr::from_bytes_with_nul(&program).unwrap();
- execv(program_c.as_ptr(), argv);
- match platform::errno {
- errno::ENOENT => (),
- other => error = other,
- }
- }
- }
- platform::errno = error;
- -1
- }
- }
- #[no_mangle]
- pub extern "C" fn fchown(fildes: c_int, owner: uid_t, group: gid_t) -> c_int {
- Sys::fchown(fildes, owner, group)
- }
- #[no_mangle]
- pub extern "C" fn fchdir(fildes: c_int) -> c_int {
- Sys::fchdir(fildes)
- }
- // #[no_mangle]
- pub extern "C" fn fdatasync(fildes: c_int) -> c_int {
- unimplemented!();
- }
- #[no_mangle]
- pub extern "C" fn fork() -> pid_t {
- let fork_hooks = unsafe { init_fork_hooks() };
- for prepare in &fork_hooks[0] {
- prepare();
- }
- let pid = Sys::fork();
- if pid == 0 {
- for child in &fork_hooks[2] {
- child();
- }
- } else if pid != -1 {
- for parent in &fork_hooks[1] {
- parent();
- }
- }
- pid
- }
- #[no_mangle]
- pub extern "C" fn fsync(fildes: c_int) -> c_int {
- Sys::fsync(fildes)
- }
- #[no_mangle]
- pub extern "C" fn ftruncate(fildes: c_int, length: off_t) -> c_int {
- Sys::ftruncate(fildes, length)
- }
- #[no_mangle]
- pub extern "C" fn getcwd(mut buf: *mut c_char, mut size: size_t) -> *mut c_char {
- let alloc = buf.is_null();
- let mut stack_buf = [0; limits::PATH_MAX];
- if alloc {
- buf = stack_buf.as_mut_ptr();
- size = stack_buf.len();
- }
- let ret = Sys::getcwd(buf, size);
- if ret.is_null() {
- return ptr::null_mut();
- }
- if alloc {
- let len = stack_buf
- .iter()
- .position(|b| *b == 0)
- .expect("no nul-byte in getcwd string")
- + 1;
- let heap_buf = unsafe { platform::alloc(len) as *mut c_char };
- for i in 0..len {
- unsafe {
- *heap_buf.add(i) = stack_buf[i];
- }
- }
- heap_buf
- } else {
- ret
- }
- }
- // #[no_mangle]
- pub extern "C" fn getdtablesize() -> c_int {
- unimplemented!();
- }
- #[no_mangle]
- pub extern "C" fn getegid() -> gid_t {
- Sys::getegid()
- }
- #[no_mangle]
- pub extern "C" fn geteuid() -> uid_t {
- Sys::geteuid()
- }
- #[no_mangle]
- pub extern "C" fn getgid() -> gid_t {
- Sys::getgid()
- }
- // #[no_mangle]
- pub extern "C" fn getgroups(gidsetsize: c_int, grouplist: *mut gid_t) -> c_int {
- unimplemented!();
- }
- // #[no_mangle]
- pub extern "C" fn gethostid() -> c_long {
- unimplemented!();
- }
- #[no_mangle]
- pub unsafe extern "C" fn gethostname(mut name: *mut c_char, mut len: size_t) -> c_int {
- let mut uts = mem::uninitialized();
- let err = Sys::uname(&mut uts);
- if err < 0 {
- mem::forget(uts);
- return err;
- }
- for c in uts.nodename.iter() {
- if len == 0 {
- break;
- }
- len -= 1;
- *name = *c;
- if *name == 0 {
- // We do want to copy the zero also, so we check this after the copying.
- break;
- }
- name = name.offset(1);
- }
- 0
- }
- #[no_mangle]
- pub unsafe extern "C" fn getlogin() -> *mut c_char {
- static mut LOGIN: [c_char; 256] = [0; 256];
- if getlogin_r(LOGIN.as_mut_ptr(), LOGIN.len()) == 0 {
- LOGIN.as_mut_ptr()
- } else {
- ptr::null_mut()
- }
- }
- #[no_mangle]
- pub extern "C" fn getlogin_r(name: *mut c_char, namesize: size_t) -> c_int {
- //TODO: Determine correct getlogin result on Redox
- unsafe { platform::errno = errno::ENOENT };
- -1
- }
- #[no_mangle]
- pub extern "C" fn getpagesize() -> c_int {
- match c_int::try_from(sysconf(_SC_PAGESIZE)) {
- Ok(page_size) => page_size,
- Err(_) => {
- /* Behavior not specified by POSIX for this case. The -1
- * value mimics sysconf()'s behavior, though.
- *
- * As specified for the limits.h header, the minimum
- * acceptable value for {PAGESIZE} is 1. The -1 value thus
- * cannot be mistaken for an acceptable value.
- *
- * POSIX does not specify any possible errors for this
- * function, hence no errno setting. */
- -1
- }
- }
- }
- // #[no_mangle]
- pub extern "C" fn getpass(prompt: *const c_char) -> *mut c_char {
- unimplemented!();
- }
- #[no_mangle]
- pub extern "C" fn getpgid(pid: pid_t) -> pid_t {
- Sys::getpgid(pid)
- }
- #[no_mangle]
- pub extern "C" fn getpgrp() -> pid_t {
- Sys::getpgid(Sys::getpid())
- }
- #[no_mangle]
- pub extern "C" fn getpid() -> pid_t {
- Sys::getpid()
- }
- #[no_mangle]
- pub extern "C" fn getppid() -> pid_t {
- Sys::getppid()
- }
- // #[no_mangle]
- pub extern "C" fn getsid(pid: pid_t) -> pid_t {
- unimplemented!();
- }
- #[no_mangle]
- pub extern "C" fn getuid() -> uid_t {
- Sys::getuid()
- }
- #[no_mangle]
- pub extern "C" fn getwd(path_name: *mut c_char) -> *mut c_char {
- getcwd(path_name, limits::PATH_MAX)
- }
- #[no_mangle]
- pub extern "C" fn isatty(fd: c_int) -> c_int {
- let mut t = termios::termios::default();
- if unsafe { termios::tcgetattr(fd, &mut t as *mut termios::termios) == 0 } {
- 1
- } else {
- 0
- }
- }
- // #[no_mangle]
- pub extern "C" fn lchown(path: *const c_char, owner: uid_t, group: gid_t) -> c_int {
- unimplemented!();
- }
- #[no_mangle]
- pub unsafe extern "C" fn link(path1: *const c_char, path2: *const c_char) -> c_int {
- let path1 = CStr::from_ptr(path1);
- let path2 = CStr::from_ptr(path2);
- Sys::link(path1, path2)
- }
- // #[no_mangle]
- pub extern "C" fn lockf(fildes: c_int, function: c_int, size: off_t) -> c_int {
- unimplemented!();
- }
- #[no_mangle]
- pub extern "C" fn lseek(fildes: c_int, offset: off_t, whence: c_int) -> off_t {
- Sys::lseek(fildes, offset, whence)
- }
- // #[no_mangle]
- pub extern "C" fn nice(incr: c_int) -> c_int {
- unimplemented!();
- }
- // #[no_mangle]
- pub extern "C" fn pause() -> c_int {
- unimplemented!();
- }
- #[no_mangle]
- pub unsafe extern "C" fn pipe(fildes: *mut c_int) -> c_int {
- pipe2(fildes, 0)
- }
- #[no_mangle]
- pub unsafe extern "C" fn pipe2(fildes: *mut c_int, flags: c_int) -> c_int {
- Sys::pipe2(slice::from_raw_parts_mut(fildes, 2), flags)
- }
- #[no_mangle]
- pub extern "C" fn pread(fildes: c_int, buf: *mut c_void, nbyte: size_t, offset: off_t) -> ssize_t {
- //TODO: better pread using system calls
- let previous = lseek(fildes, offset, SEEK_SET);
- if previous == -1 {
- return -1;
- }
- let res = read(fildes, buf, nbyte);
- if res < 0 {
- return res;
- }
- if lseek(fildes, previous, SEEK_SET) == -1 {
- return -1;
- }
- res
- }
- #[no_mangle]
- pub extern "C" fn pthread_atfork(
- prepare: Option<extern "C" fn()>,
- parent: Option<extern "C" fn()>,
- child: Option<extern "C" fn()>,
- ) -> c_int {
- let fork_hooks = unsafe { init_fork_hooks() };
- if let Some(prepare) = prepare {
- fork_hooks[0].push_back(prepare);
- }
- if let Some(parent) = parent {
- fork_hooks[1].push_back(parent);
- }
- if let Some(child) = child {
- fork_hooks[2].push_back(child);
- }
- 0
- }
- #[no_mangle]
- pub extern "C" fn pwrite(
- fildes: c_int,
- buf: *const c_void,
- nbyte: size_t,
- offset: off_t,
- ) -> ssize_t {
- //TODO: better pwrite using system calls
- let previous = lseek(fildes, offset, SEEK_SET);
- if previous == -1 {
- return -1;
- }
- let res = write(fildes, buf, nbyte);
- if res < 0 {
- return res;
- }
- if lseek(fildes, previous, SEEK_SET) == -1 {
- return -1;
- }
- res
- }
- #[no_mangle]
- pub extern "C" fn read(fildes: c_int, buf: *const c_void, nbyte: size_t) -> ssize_t {
- let buf = unsafe { slice::from_raw_parts_mut(buf as *mut u8, nbyte as usize) };
- trace_expr!(
- Sys::read(fildes, buf),
- "read({}, {:p}, {})",
- fildes,
- buf,
- nbyte
- )
- }
- #[no_mangle]
- pub unsafe extern "C" fn readlink(
- path: *const c_char,
- buf: *mut c_char,
- bufsize: size_t,
- ) -> ssize_t {
- let path = CStr::from_ptr(path);
- let buf = slice::from_raw_parts_mut(buf as *mut u8, bufsize as usize);
- Sys::readlink(path, buf)
- }
- #[no_mangle]
- pub unsafe extern "C" fn rmdir(path: *const c_char) -> c_int {
- let path = CStr::from_ptr(path);
- Sys::rmdir(path)
- }
- #[no_mangle]
- pub extern "C" fn setgid(gid: gid_t) -> c_int {
- Sys::setregid(gid, gid)
- }
- #[no_mangle]
- pub extern "C" fn setpgid(pid: pid_t, pgid: pid_t) -> c_int {
- Sys::setpgid(pid, pgid)
- }
- #[no_mangle]
- pub extern "C" fn setpgrp() -> pid_t {
- setpgid(0, 0)
- }
- #[no_mangle]
- pub extern "C" fn setregid(rgid: gid_t, egid: gid_t) -> c_int {
- Sys::setregid(rgid, egid)
- }
- #[no_mangle]
- pub extern "C" fn setreuid(ruid: uid_t, euid: uid_t) -> c_int {
- Sys::setreuid(ruid, euid)
- }
- // #[no_mangle]
- pub extern "C" fn setsid() -> pid_t {
- unimplemented!();
- }
- #[no_mangle]
- pub extern "C" fn setuid(uid: uid_t) -> c_int {
- Sys::setreuid(uid, uid)
- }
- #[no_mangle]
- pub extern "C" fn sleep(seconds: c_uint) -> c_uint {
- let rqtp = timespec {
- tv_sec: seconds as i64,
- tv_nsec: 0,
- };
- let rmtp = ptr::null_mut();
- Sys::nanosleep(&rqtp, rmtp);
- 0
- }
- #[no_mangle]
- pub extern "C" fn swab(src: *const c_void, dest: *mut c_void, nbytes: ssize_t) {
- if nbytes <= 0 {
- return;
- }
- let number_of_swaps = nbytes / 2;
- let mut offset = 0;
- for i in 0..number_of_swaps {
- unsafe {
- src.offset(offset).copy_to(dest.offset(offset + 1), 1);
- src.offset(offset + 1).copy_to(dest.offset(offset), 1);
- }
- offset += 2;
- }
- }
- #[no_mangle]
- pub unsafe extern "C" fn symlink(path1: *const c_char, path2: *const c_char) -> c_int {
- let path1 = CStr::from_ptr(path1);
- let path2 = CStr::from_ptr(path2);
- Sys::symlink(path1, path2)
- }
- // #[no_mangle]
- pub extern "C" fn sync() {
- unimplemented!();
- }
- #[no_mangle]
- pub extern "C" fn tcgetpgrp(fd: c_int) -> pid_t {
- let mut pgrp = 0;
- if unsafe { sys_ioctl::ioctl(fd, sys_ioctl::TIOCGPGRP, &mut pgrp as *mut pid_t as _) } < 0 {
- return -1;
- }
- pgrp
- }
- #[no_mangle]
- pub extern "C" fn tcsetpgrp(fd: c_int, pgrp: pid_t) -> c_int {
- if unsafe { sys_ioctl::ioctl(fd, sys_ioctl::TIOCSPGRP, &pgrp as *const pid_t as _) } < 0 {
- return -1;
- }
- pgrp
- }
- // #[no_mangle]
- pub extern "C" fn truncate(path: *const c_char, length: off_t) -> c_int {
- unimplemented!();
- }
- #[no_mangle]
- pub unsafe extern "C" fn ttyname(fildes: c_int) -> *mut c_char {
- static mut TTYNAME: [c_char; 4096] = [0; 4096];
- if ttyname_r(fildes, TTYNAME.as_mut_ptr(), TTYNAME.len()) == 0 {
- TTYNAME.as_mut_ptr()
- } else {
- ptr::null_mut()
- }
- }
- #[no_mangle]
- pub extern "C" fn ttyname_r(fildes: c_int, name: *mut c_char, namesize: size_t) -> c_int {
- let name = unsafe { slice::from_raw_parts_mut(name as *mut u8, namesize) };
- if name.is_empty() {
- return errno::ERANGE;
- }
- let len = Sys::fpath(fildes, &mut name[..namesize - 1]);
- if len < 0 {
- return unsafe { -platform::errno };
- }
- name[len as usize] = 0;
- 0
- }
- #[no_mangle]
- pub extern "C" fn ualarm(usecs: useconds_t, interval: useconds_t) -> useconds_t {
- let mut timer = sys_time::itimerval {
- it_value: sys_time::timeval {
- tv_sec: 0,
- tv_usec: usecs as suseconds_t,
- },
- it_interval: sys_time::timeval {
- tv_sec: 0,
- tv_usec: interval as suseconds_t,
- },
- };
- let errno_backup = unsafe { platform::errno };
- let ret = if sys_time::setitimer(sys_time::ITIMER_REAL, &timer, &mut timer) < 0 {
- 0
- } else {
- timer.it_value.tv_sec as useconds_t * 1_000_000 + timer.it_value.tv_usec as useconds_t
- };
- unsafe {
- platform::errno = errno_backup;
- }
- ret
- }
- #[no_mangle]
- pub unsafe extern "C" fn unlink(path: *const c_char) -> c_int {
- let path = CStr::from_ptr(path);
- Sys::unlink(path)
- }
- #[no_mangle]
- pub extern "C" fn usleep(useconds: useconds_t) -> c_int {
- let rqtp = timespec {
- tv_sec: (useconds / 1_000_000) as i64,
- tv_nsec: ((useconds % 1_000_000) * 1000) as i64,
- };
- let rmtp = ptr::null_mut();
- Sys::nanosleep(&rqtp, rmtp)
- }
- // #[no_mangle]
- pub extern "C" fn vfork() -> pid_t {
- unimplemented!();
- }
- #[no_mangle]
- pub extern "C" fn write(fildes: c_int, buf: *const c_void, nbyte: size_t) -> ssize_t {
- let buf = unsafe { slice::from_raw_parts(buf as *const u8, nbyte as usize) };
- Sys::write(fildes, buf)
- }
|