diff --git a/src/header/sys_ioctl/linux.rs b/src/header/sys_ioctl/linux.rs index 02cc8c9fc2c77b5534a35530066abc1311e00067..e5f39c682898db036c7112af1b98fb6ca5788853 100644 --- a/src/header/sys_ioctl/linux.rs +++ b/src/header/sys_ioctl/linux.rs @@ -2,7 +2,7 @@ use platform::types::*; use platform::Sys; #[no_mangle] -pub extern "C" fn ioctl(fd: c_int, request: c_ulong, out: *mut c_void) -> c_int { +pub unsafe extern "C" fn ioctl(fd: c_int, request: c_ulong, out: *mut c_void) -> c_int { // TODO: Somehow support varargs to syscall?? Sys::ioctl(fd, request, out) } diff --git a/src/header/sys_ioctl/redox.rs b/src/header/sys_ioctl/redox.rs index 6d0f0257302454ebe7b631a5a93502ec7e438cca..4494fa80a2f35c73a3dee6d43abae9c42b026bd5 100644 --- a/src/header/sys_ioctl/redox.rs +++ b/src/header/sys_ioctl/redox.rs @@ -11,6 +11,39 @@ use super::winsize; #[no_mangle] pub unsafe extern "C" fn ioctl(fd: c_int, request: c_ulong, out: *mut c_void) -> c_int { match request { + TCGETS => { + let dup = e(syscall::dup(fd as usize, b"termios")); + if dup == !0 { + return -1; + } + + let count = e(syscall::read(dup, unsafe { + slice::from_raw_parts_mut(out as *mut u8, mem::size_of::<termios>()) + })); + let _ = syscall::close(dup); + + if count == !0 { + return -1; + } + 0 + } + + TCSETS => { + let dup = e(syscall::dup(fd as usize, b"termios")); + if dup == !0 { + return -1; + } + + let count = e(syscall::write(dup, unsafe { + slice::from_raw_parts(out as *const u8, mem::size_of::<termios>()) + })); + let _ = syscall::close(dup); + + if count == !0 { + return -1; + } + 0 + }, TIOCGPGRP => { let dup = e(syscall::dup(fd as usize, b"pgrp")); if dup == !0 { @@ -86,6 +119,9 @@ pub unsafe extern "C" fn ioctl(fd: c_int, request: c_ulong, out: *mut c_void) -> } } +pub const TCGETS: c_ulong = 0x5401; +pub const TCSETS: c_ulong = 0x5402; + pub const TIOCGPGRP: c_ulong = 0x540F; pub const TIOCSPGRP: c_ulong = 0x5410; diff --git a/src/header/termios/mod.rs b/src/header/termios/mod.rs index e60e35a2d163cfedc9798ac228ac088108d81c33..eb8978b564e1e97f8736ff6e3f43e4d17c4e8779 100644 --- a/src/header/termios/mod.rs +++ b/src/header/termios/mod.rs @@ -1,9 +1,9 @@ //! termios implementation, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/termios.h.html use header::errno; +use header::sys_ioctl; use platform; use platform::types::*; -use platform::{Pal, Sys}; pub type cc_t = u8; pub type speed_t = u32; @@ -12,6 +12,7 @@ pub type tcflag_t = u32; pub const NCCS: usize = 32; #[repr(C)] +#[derive(Default)] pub struct termios { c_iflag: tcflag_t, c_oflag: tcflag_t, @@ -24,13 +25,18 @@ pub struct termios { } #[no_mangle] -pub extern "C" fn tcgetattr(fd: c_int, out: *mut termios) -> c_int { - Sys::tcgetattr(fd, out) +pub unsafe extern "C" fn tcgetattr(fd: c_int, out: *mut termios) -> c_int { + sys_ioctl::ioctl(fd, sys_ioctl::TCGETS, out as *mut c_void) } #[no_mangle] -pub extern "C" fn tcsetattr(fd: c_int, act: c_int, value: *mut termios) -> c_int { - Sys::tcsetattr(fd, act, value) +pub unsafe extern "C" fn tcsetattr(fd: c_int, act: c_int, value: *mut termios) -> c_int { + if act < 0 || act > 2 { + platform::errno = errno::EINVAL; + return -1; + } + // This is safe because ioctl shouldn't modify the value + sys_ioctl::ioctl(fd, sys_ioctl::TCSETS + act as c_ulong, value as *mut c_void) } #[no_mangle] diff --git a/src/header/unistd/mod.rs b/src/header/unistd/mod.rs index e8bf0fd9611eae256de0e4a4d9fb59f531559666..173104adcf48e8dbe8128a166f378a111aeaad33 100644 --- a/src/header/unistd/mod.rs +++ b/src/header/unistd/mod.rs @@ -8,6 +8,7 @@ use header::limits; use header::stdlib::getenv; use header::sys_ioctl; use header::sys_time; +use header::termios; use header::time::timespec; use platform; use platform::types::*; @@ -378,7 +379,12 @@ pub extern "C" fn getwd(path_name: *mut c_char) -> *mut c_char { #[no_mangle] pub extern "C" fn isatty(fd: c_int) -> c_int { - Sys::isatty(fd) + let mut t = termios::termios::default(); + if unsafe { termios::tcgetattr(fd, &mut t as *mut termios::termios) == 0 } { + 1 + } else { + 0 + } } // #[no_mangle] diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 26003962eb43fe148e858a98b0e5204f3a6e7d3e..d9611da1c02b24917b4268f35212e245ecaf97ec 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -6,11 +6,9 @@ use super::{errno, Pal}; use c_str::CStr; use fs::File; use header::dirent::dirent; -use header::errno::EINVAL; use header::fcntl; use header::poll::{nfds_t, pollfd}; use header::signal::SIGCHLD; -use header::sys_ioctl::{winsize, TCGETS, TCSETS, TIOCGWINSZ}; // use header::sys_resource::rusage; use header::sys_select::fd_set; use header::sys_stat::stat; @@ -18,7 +16,6 @@ use header::sys_statvfs::statvfs; use header::sys_time::{timeval, timezone}; // use header::sys_times::tms; use header::sys_utsname::utsname; -use header::termios::termios; use header::time::timespec; mod signal; @@ -68,9 +65,9 @@ impl Sys { // e(unsafe { syscall!(GETRUSAGE, who, r_usage) }) as c_int // } - pub fn ioctl(fd: c_int, request: c_ulong, out: *mut c_void) -> c_int { + pub unsafe fn ioctl(fd: c_int, request: c_ulong, out: *mut c_void) -> c_int { // TODO: Somehow support varargs to syscall?? - e(unsafe { syscall!(IOCTL, fd, request, out) }) as c_int + e(syscall!(IOCTL, fd, request, out)) as c_int } // fn times(out: *mut tms) -> clock_t { @@ -260,11 +257,6 @@ impl Pal for Sys { e(unsafe { syscall!(GETUID) }) as uid_t } - fn isatty(fd: c_int) -> c_int { - let mut winsize = winsize::default(); - (Self::ioctl(fd, TIOCGWINSZ, &mut winsize as *mut _ as *mut c_void) == 0) as c_int - } - fn link(path1: &CStr, path2: &CStr) -> c_int { e(unsafe { syscall!( @@ -424,21 +416,6 @@ impl Pal for Sys { e(unsafe { syscall!(SYMLINKAT, path1.as_ptr(), AT_FDCWD, path2.as_ptr()) }) as c_int } - fn tcgetattr(fd: c_int, out: *mut termios) -> c_int { - Self::ioctl(fd, TCGETS, out as *mut c_void) - } - - fn tcsetattr(fd: c_int, act: c_int, value: *const termios) -> c_int { - if act < 0 || act > 2 { - unsafe { - errno = EINVAL; - } - return -1; - } - // This is safe because ioctl shouldn't modify the value - Self::ioctl(fd, TCSETS + act as c_ulong, value as *mut c_void) - } - fn umask(mask: mode_t) -> mode_t { unsafe { syscall!(UMASK, mask) as mode_t } } diff --git a/src/platform/pal/mod.rs b/src/platform/pal/mod.rs index bae5380a9d4904c0bf1bc668f8996339c5821b2d..211b9554b97491bc52707ce40fd319bc7ae0a977 100644 --- a/src/platform/pal/mod.rs +++ b/src/platform/pal/mod.rs @@ -7,7 +7,6 @@ use header::sys_stat::stat; use header::sys_statvfs::statvfs; use header::sys_time::{timeval, timezone}; use header::sys_utsname::utsname; -use header::termios::termios; use header::time::timespec; pub use self::signal::PalSignal; @@ -87,8 +86,6 @@ pub trait Pal { fn getuid() -> uid_t; - fn isatty(fd: c_int) -> c_int; - fn link(path1: &CStr, path2: &CStr) -> c_int; fn lseek(fildes: c_int, offset: off_t, whence: c_int) -> off_t; @@ -149,10 +146,6 @@ pub trait Pal { fn symlink(path1: &CStr, path2: &CStr) -> c_int; - fn tcgetattr(fd: c_int, out: *mut termios) -> c_int; - - fn tcsetattr(fd: c_int, act: c_int, value: *const termios) -> c_int; - fn umask(mask: mode_t) -> mode_t; fn uname(utsname: *mut utsname) -> c_int; diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 5fb4d4e618ed4ba93b74279ea264ba198ac10cbe..86f2396a0f66d64de9c6d9e690508907e84b5506 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -21,7 +21,6 @@ use header::sys_stat::stat; use header::sys_statvfs::statvfs; use header::sys_time::{timeval, timezone}; use header::sys_utsname::{utsname, UTSLENGTH}; -use header::termios::termios; use header::time::timespec; use header::unistd::{F_OK, R_OK, W_OK, X_OK}; use io::prelude::*; @@ -576,15 +575,6 @@ impl Pal for Sys { e(syscall::getuid()) as pid_t } - fn isatty(fd: c_int) -> c_int { - syscall::dup(fd as usize, b"termios") - .map(|fd| { - let _ = syscall::close(fd); - 1 - }) - .unwrap_or(0) - } - fn link(path1: &CStr, path2: &CStr) -> c_int { e(unsafe { syscall::link(path1.as_ptr() as *const u8, path2.as_ptr() as *const u8) }) as c_int @@ -1064,40 +1054,6 @@ impl Pal for Sys { 0 } - fn tcgetattr(fd: c_int, out: *mut termios) -> c_int { - let dup = e(syscall::dup(fd as usize, b"termios")); - if dup == !0 { - return -1; - } - - let read = e(syscall::read(dup, unsafe { - slice::from_raw_parts_mut(out as *mut u8, mem::size_of::<termios>()) - })); - let _ = syscall::close(dup); - - if read == !0 { - return -1; - } - 0 - } - - fn tcsetattr(fd: c_int, _act: c_int, value: *const termios) -> c_int { - let dup = e(syscall::dup(fd as usize, b"termios")); - if dup == !0 { - return -1; - } - - let write = e(syscall::write(dup, unsafe { - slice::from_raw_parts(value as *const u8, mem::size_of::<termios>()) - })); - let _ = syscall::close(dup); - - if write == !0 { - return -1; - } - 0 - } - fn umask(mask: mode_t) -> mode_t { e(syscall::umask(mask as usize)) as mode_t }