Verified Commit a8893338 authored by Jeremy Soller's avatar Jeremy Soller
Browse files

Implement termios functions using ioctl

parent 047decee
......@@ -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)
}
......
......@@ -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;
......
//! 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]
......
......@@ -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]
......
......@@ -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 }
}
......
......@@ -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;
......
......@@ -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
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment