diff --git a/Cargo.lock b/Cargo.lock index 259c5974efa70e0d70d5f8cdcadead1a6815612a..9bf6efb87daac03a40baea146a417a6a2571b336 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -337,7 +337,6 @@ dependencies = [ "pwd 0.1.0", "semaphore 0.1.0", "setjmp 0.1.0", - "sgtty 0.1.0", "signal 0.1.0", "stdio 0.1.0", "stdlib 0.1.0", @@ -354,6 +353,7 @@ dependencies = [ "sys_un 0.1.0", "sys_utsname 0.1.0", "sys_wait 0.1.0", + "termios 0.1.0", "time 0.1.0", "unistd 0.1.0", "utime 0.1.0", @@ -423,15 +423,6 @@ dependencies = [ name = "setjmp" version = "0.1.0" -[[package]] -name = "sgtty" -version = "0.1.0" -dependencies = [ - "cbindgen 0.5.2", - "platform 0.1.0", - "sys_ioctl 0.1.0", -] - [[package]] name = "signal" version = "0.1.0" @@ -643,6 +634,14 @@ dependencies = [ "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "termios" +version = "0.1.0" +dependencies = [ + "cbindgen 0.5.2", + "platform 0.1.0", +] + [[package]] name = "textwrap" version = "0.10.0" diff --git a/Cargo.toml b/Cargo.toml index cc49b5c186b3c6c93aed2ecd4fac800aa83a4722..1567fd447fbbe1cf6dd16e9a655e28034f4c7c6a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,6 @@ platform = { path = "src/platform" } pwd = { path = "src/pwd" } semaphore = { path = "src/semaphore" } setjmp = { path = "src/setjmp" } -sgtty = { path = "src/sgtty" } signal = { path = "src/signal" } stdio = { path = "src/stdio" } stdlib = { path = "src/stdlib" } @@ -46,6 +45,7 @@ sys_times = { path = "src/sys_times" } sys_un = { path = "src/sys_un" } sys_utsname = { path = "src/sys_utsname" } sys_wait = { path = "src/sys_wait" } +termios = { path = "src/termios" } time = { path = "src/time" } unistd = { path = "src/unistd" } utime = { path = "src/utime" } diff --git a/include/bits/sys/stat.h b/include/bits/sys/stat.h index b9ae34fefc5b386a8c295b1607799de2a7a852e5..0078da854bc1c69dd78da7fe5a177f6d574fd4ff 100644 --- a/include/bits/sys/stat.h +++ b/include/bits/sys/stat.h @@ -10,5 +10,6 @@ #define st_atime st_atim.tv_sec #define st_mtime st_mtim.tv_sec +#define st_ctime st_ctim.tv_sec #endif diff --git a/include/bits/unistd.h b/include/bits/unistd.h index a7167d047a4988f8fce0372e674c4a4514663fb1..e37f3d2ad2ff899d17422be4bfc6f55ce03a2098 100644 --- a/include/bits/unistd.h +++ b/include/bits/unistd.h @@ -1,6 +1,8 @@ #ifndef _BITS_UNISTD_H #define _BITS_UNISTD_H +#define _POSIX_VERSION 200809L + int execl(const char *path, const char* argv0, ...); int execle(const char *path, const char* argv0, ...); diff --git a/src/lib.rs b/src/lib.rs index c085bd8120ed22c9d8acd6a2ace7626478e400a5..1a1802758970c2388ca5365de3ae153f4c0f055f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,7 +19,6 @@ pub extern crate netinet; pub extern crate pwd; pub extern crate semaphore; pub extern crate setjmp; -pub extern crate sgtty; pub extern crate signal; pub extern crate stdio; pub extern crate stdlib; @@ -36,6 +35,7 @@ pub extern crate sys_times; pub extern crate sys_un; pub extern crate sys_utsname; pub extern crate sys_wait; +pub extern crate termios; pub extern crate time; pub extern crate unistd; pub extern crate utime; diff --git a/src/platform/src/linux/mod.rs b/src/platform/src/linux/mod.rs index 14765b6c5a5bfa5d61860f74d7d28ec5303a3461..e7018fbfcfa238b67d8da1e58d5686d374c200db 100644 --- a/src/platform/src/linux/mod.rs +++ b/src/platform/src/linux/mod.rs @@ -3,6 +3,10 @@ use core::{mem, ptr}; use errno; use types::*; +const EINVAL: c_int = 22; + +const TCGETS: c_ulong = 0x5401; +const TCSETS: c_ulong = 0x5402; const TIOCGWINSZ: c_ulong = 0x5413; const AT_FDCWD: c_int = -100; @@ -420,6 +424,21 @@ pub fn socketpair(domain: c_int, kind: c_int, protocol: c_int, socket_vector: *m e(unsafe { syscall!(SOCKETPAIR, domain, kind, protocol, socket_vector) }) as c_int } +pub fn tcgetattr(fd: c_int, out: *mut termios) -> c_int { + ioctl(fd, TCGETS, out as *mut c_void) +} + +pub 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 + ioctl(fd, TCSETS + act as c_ulong, value as *mut c_void) +} + pub fn times(out: *mut tms) -> clock_t { unsafe { syscall!(TIMES, out) as clock_t } } diff --git a/src/platform/src/redox/mod.rs b/src/platform/src/redox/mod.rs index 75cbc771fa6de89e534e48a8d644b639d07066d0..691bf3c746459b54484a32913cbb8c3c790990be 100644 --- a/src/platform/src/redox/mod.rs +++ b/src/platform/src/redox/mod.rs @@ -992,6 +992,42 @@ pub fn socketpair(domain: c_int, kind: c_int, protocol: c_int, socket_vector: *m -1 } +pub 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 +} + +pub 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 +} + pub fn times(out: *mut tms) -> clock_t { let _ = write!(FileWriter(2), "unimplemented: times({:p})", out); !0 diff --git a/src/platform/src/types.rs b/src/platform/src/types.rs index 5ac9ab3a3071b2f65e389ace02988575e69df2c3..bb09f4e22790df6e589f5a2f957c5c6dd2006e4f 100644 --- a/src/platform/src/types.rs +++ b/src/platform/src/types.rs @@ -241,3 +241,21 @@ 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 type cc_t = u8; +pub type speed_t = u32; +pub type tcflag_t = u32; + +pub const NCCS: usize = 32; + +#[repr(C)] +pub struct termios { + c_iflag: tcflag_t, + c_oflag: tcflag_t, + c_cflag: tcflag_t, + c_lflag: tcflag_t, + c_line: cc_t, + c_cc: [cc_t; NCCS], + __c_ispeed: speed_t, + __c_ospeed: speed_t +} diff --git a/src/termios/Cargo.toml b/src/termios/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..4fa692f2fff4b6d52866576c2a98fa27751a8412 --- /dev/null +++ b/src/termios/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "termios" +version = "0.1.0" +authors = ["jD91mZM2 <me@krake.one>"] + +[build-dependencies] +cbindgen = { path = "../../cbindgen" } + +[dependencies] +platform = { path = "../platform" } diff --git a/src/termios/build.rs b/src/termios/build.rs new file mode 100644 index 0000000000000000000000000000000000000000..da15d4a9b482a03acf8a3277964660e5e4ea029c --- /dev/null +++ b/src/termios/build.rs @@ -0,0 +1,11 @@ +extern crate cbindgen; + +use std::{env, fs}; + +fn main() { + let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set"); + fs::create_dir_all("../../target/include").expect("failed to create include directory"); + cbindgen::generate(crate_dir) + .expect("failed to generate bindings") + .write_to_file("../../target/include/termios.h"); +} diff --git a/src/termios/cbindgen.toml b/src/termios/cbindgen.toml new file mode 100644 index 0000000000000000000000000000000000000000..1cc6fde37cf78050d485d0fb6a5e02a337298348 --- /dev/null +++ b/src/termios/cbindgen.toml @@ -0,0 +1,7 @@ +sys_includes = ["stdint.h"] +include_guard = "_TERMIOS_H" +language = "C" +style = "Tag" + +[enum] +prefix_with_name = true diff --git a/src/termios/src/lib.rs b/src/termios/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..e7306f76fc0189f3531ba1ed196463baa7a642b1 --- /dev/null +++ b/src/termios/src/lib.rs @@ -0,0 +1,149 @@ +//! termios implementation, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/termios.h.html +#![no_std] + +extern crate platform; + +use platform::types::*; + +pub type cc_t = u8; +pub type speed_t = u32; +pub type tcflag_t = u32; + +pub const NCCS: usize = 32; + +#[repr(C)] +pub struct termios { + c_iflag: tcflag_t, + c_oflag: tcflag_t, + c_cflag: tcflag_t, + c_lflag: tcflag_t, + c_line: cc_t, + c_cc: [cc_t; NCCS], + __c_ispeed: speed_t, + __c_ospeed: speed_t +} + +#[no_mangle] +pub extern "C" fn tcgetattr(fd: c_int, out: *mut termios) -> c_int { + platform::tcgetattr(fd, out as *mut platform::types::termios) +} + +#[no_mangle] +pub extern "C" fn tcsetattr(fd: c_int, act: c_int, value: *mut termios) -> c_int { + platform::tcsetattr(fd, act, value as *mut platform::types::termios) +} + +pub const VINTR: usize = 0; +pub const VQUIT: usize = 1; +pub const VERASE: usize = 2; +pub const VKILL: usize = 3; +pub const VEOF: usize = 4; +pub const VTIME: usize = 5; +pub const VMIN: usize = 6; +pub const VSWTC: usize = 7; +pub const VSTART: usize = 8; +pub const VSTOP: usize = 9; +pub const VSUSP: usize = 10; +pub const VEOL: usize = 11; +pub const VREPRINT: usize = 12; +pub const VDISCARD: usize = 13; +pub const VWERASE: usize = 14; +pub const VLNEXT: usize = 15; +pub const VEOL2: usize = 16; + +pub const IGNBRK: usize = 0o000001; +pub const BRKINT: usize = 0o000002; +pub const IGNPAR: usize = 0o000004; +pub const PARMRK: usize = 0o000010; +pub const INPCK: usize = 0o000020; +pub const ISTRIP: usize = 0o000040; +pub const INLCR: usize = 0o000100; +pub const IGNCR: usize = 0o000200; +pub const ICRNL: usize = 0o000400; +pub const IUCLC: usize = 0o001000; +pub const IXON: usize = 0o002000; +pub const IXANY: usize = 0o004000; +pub const IXOFF: usize = 0o010000; +pub const IMAXBEL: usize = 0o020000; +pub const IUTF8: usize = 0o040000; + +pub const OPOST: usize = 0o000001; +pub const OLCUC: usize = 0o000002; +pub const ONLCR: usize = 0o000004; +pub const OCRNL: usize = 0o000010; +pub const ONOCR: usize = 0o000020; +pub const ONLRET: usize = 0o000040; +pub const OFILL: usize = 0o000100; +pub const OFDEL: usize = 0o000200; + +pub const VTDLY: usize = 0o040000; +pub const VT0: usize = 0o000000; +pub const VT1: usize = 0o040000; + +pub const B0: usize = 0o000000; +pub const B50: usize = 0o000001; +pub const B75: usize = 0o000002; +pub const B110: usize = 0o000003; +pub const B134: usize = 0o000004; +pub const B150: usize = 0o000005; +pub const B200: usize = 0o000006; +pub const B300: usize = 0o000007; +pub const B600: usize = 0o000010; +pub const B1200: usize = 0o000011; +pub const B1800: usize = 0o000012; +pub const B2400: usize = 0o000013; +pub const B4800: usize = 0o000014; +pub const B9600: usize = 0o000015; +pub const B19200: usize = 0o000016; +pub const B38400: usize = 0o000017; + +pub const B57600: usize = 0o010001; +pub const B115200: usize = 0o010002; +pub const B230400: usize = 0o010003; +pub const B460800: usize = 0o010004; +pub const B500000: usize = 0o010005; +pub const B576000: usize = 0o010006; +pub const B921600: usize = 0o010007; +pub const B1000000: usize = 0o010010; +pub const B1152000: usize = 0o010011; +pub const B1500000: usize = 0o010012; +pub const B2000000: usize = 0o010013; +pub const B2500000: usize = 0o010014; +pub const B3000000: usize = 0o010015; +pub const B3500000: usize = 0o010016; +pub const B4000000: usize = 0o010017; + +pub const CSIZE: usize = 0o000060; +pub const CS5: usize = 0o000000; +pub const CS6: usize = 0o000020; +pub const CS7: usize = 0o000040; +pub const CS8: usize = 0o000060; +pub const CSTOPB: usize = 0o000100; +pub const CREAD: usize = 0o000200; +pub const PARENB: usize = 0o000400; +pub const PARODD: usize = 0o001000; +pub const HUPCL: usize = 0o002000; +pub const CLOCAL: usize = 0o004000; + +pub const ISIG: usize = 0o000001; +pub const ICANON: usize = 0o000002; +pub const ECHO: usize = 0o000010; +pub const ECHOE: usize = 0o000020; +pub const ECHOK: usize = 0o000040; +pub const ECHONL: usize = 0o000100; +pub const NOFLSH: usize = 0o000200; +pub const TOSTOP: usize = 0o000400; +pub const IEXTEN: usize = 0o100000; + +pub const TCOOFF: usize = 0; +pub const TCOON: usize = 1; +pub const TCIOFF: usize = 2; +pub const TCION: usize = 3; + +pub const TCIFLUSH: usize = 0; +pub const TCOFLUSH: usize = 1; +pub const TCIOFLUSH: usize = 2; + +pub const TCSANOW: usize = 0; +pub const TCSADRAIN: usize = 1; +pub const TCSAFLUSH: usize = 2; diff --git a/src/time/src/lib.rs b/src/time/src/lib.rs index 3bfc2c8fe21c88ff0047d13110a5691603b34bec..7bec8d3749afe96c44725e1c429dfdf4adc82443 100644 --- a/src/time/src/lib.rs +++ b/src/time/src/lib.rs @@ -287,7 +287,7 @@ pub unsafe extern "C" fn localtime_r(clock: *const time_t, t: *mut tm) -> *mut t } #[no_mangle] -pub unsafe extern "C" fn mktime(t: *const tm) -> time_t { +pub unsafe extern "C" fn mktime(t: *mut tm) -> time_t { let mut year = (*t).tm_year + 1900; let mut month = (*t).tm_mon; let mut day = (*t).tm_mday as i64 - 1; diff --git a/src/time/src/strftime.rs b/src/time/src/strftime.rs index 9ffedc197542b77559b6a516f23bb7ade0255e40..b616b1c0e8d24862a2b6ab7bb712f79bfe899044 100644 --- a/src/time/src/strftime.rs +++ b/src/time/src/strftime.rs @@ -120,7 +120,8 @@ pub unsafe fn strftime<W: Write>( b'P' => w!(if (*t).tm_hour < 12 { "am" } else { "pm" }), b'r' => w!(recurse "%I:%M:%S %p"), b'R' => w!(recurse "%H:%M"), - b's' => w!("{}", ::mktime(t)), + // Nothing is modified in mktime, but the C standard of course requires a mutable pointer ._. + b's' => w!("{}", ::mktime(t as *mut tm)), b'S' => w!("{:02}", (*t).tm_sec), b'T' => w!(recurse "%H:%M:%S"), b'u' => w!("{}", ((*t).tm_wday + 7 - 1) % 7 + 1),