Add basic linux termios implementation

This commit is contained in:
nofmal 2020-01-30 13:36:28 +07:00 committed by Andrew Kelley
parent 0fdcd5c4cb
commit a697de3eac
4 changed files with 116 additions and 0 deletions

View File

@ -119,6 +119,8 @@ pub extern "c" fn getrusage(who: c_int, usage: *rusage) c_int;
pub extern "c" fn sysctl(name: [*]const c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;
pub extern "c" fn sysctlbyname(name: [*:0]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;
pub extern "c" fn sysctlnametomib(name: [*:0]const u8, mibp: ?*c_int, sizep: ?*usize) c_int;
pub extern "c" fn tcgetattr(fd: fd_t, termios_p: *termios) c_int;
pub extern "c" fn tcsetattr(fd: fd_t, optional_action: TCSA, termios_p: *const termios) c_int;
pub extern "c" fn gethostname(name: [*]u8, len: usize) c_int;
pub extern "c" fn bind(socket: fd_t, address: ?*const sockaddr, address_len: socklen_t) c_int;

View File

@ -3327,3 +3327,35 @@ pub fn getrusage(who: i32) rusage {
else => unreachable,
}
}
pub const TermiosGetError = error{
NotATerminal,
} || UnexpectedError;
pub fn tcgetattr(handle: fd_t) TermiosGetError!termios {
var term: termios = undefined;
switch (errno(system.tcgetattr(handle, &term))) {
0 => return term,
EBADF => unreachable,
ENOTTY => return error.NotATerminal,
else => |err| return unexpectedErrno(err),
}
}
pub const TermiosSetError = TermiosGetError || error{
ProcessOrphaned,
};
pub fn tcsetattr(handle: fd_t, optional_action: TCSA, termios_p: termios) TermiosSetError!void {
while (true) {
switch (errno(system.tcsetattr(handle, optional_action, &termios_p))) {
0 => return,
EBADF => unreachable,
EINTR => continue,
EINVAL => unreachable,
ENOTTY => return error.NotATerminal,
EIO => return error.ProcessOrphaned,
else => |err| return unexpectedErrno(err),
}
}
}

View File

@ -1515,3 +1515,77 @@ pub const rusage = extern struct {
nivcsw: isize,
__reserved: [16]isize = [1]isize{0} ** 16,
};
pub const cc_t = u8;
pub const speed_t = u32;
pub const tcflag_t = u32;
pub const NCCS = 32;
pub const IGNBRK = 1;
pub const BRKINT = 2;
pub const IGNPAR = 4;
pub const PARMRK = 8;
pub const INPCK = 16;
pub const ISTRIP = 32;
pub const INLCR = 64;
pub const IGNCR = 128;
pub const ICRNL = 256;
pub const IUCLC = 512;
pub const IXON = 1024;
pub const IXANY = 2048;
pub const IXOFF = 4096;
pub const IMAXBEL = 8192;
pub const IUTF8 = 16384;
pub const OPOST = 1;
pub const OLCUC = 2;
pub const ONLCR = 4;
pub const OCRNL = 8;
pub const ONOCR = 16;
pub const ONLRET = 32;
pub const OFILL = 64;
pub const OFDEL = 128;
pub const VTDLY = 16384;
pub const VT0 = 0;
pub const VT1 = 16384;
pub const CSIZE = 48;
pub const CS5 = 0;
pub const CS6 = 16;
pub const CS7 = 32;
pub const CS8 = 48;
pub const CSTOPB = 64;
pub const CREAD = 128;
pub const PARENB = 256;
pub const PARODD = 512;
pub const HUPCL = 1024;
pub const CLOCAL = 2048;
pub const ISIG = 1;
pub const ICANON = 2;
pub const ECHO = 8;
pub const ECHOE = 16;
pub const ECHOK = 32;
pub const ECHONL = 64;
pub const NOFLSH = 128;
pub const TOSTOP = 256;
pub const IEXTEN = 32768;
pub const TCSA = extern enum(usize) {
NOW,
DRAIN,
FLUSH,
_,
};
pub const termios = extern struct {
iflag: tcflag_t,
oflag: tcflag_t,
cflag: tcflag_t,
lflag: tcflag_t,
line: cc_t,
cc: [NCCS]cc_t,
ispeed: speed_t,
ospeed: speed_t,
};

View File

@ -1061,6 +1061,14 @@ pub fn getrusage(who: i32, usage: *rusage) usize {
return syscall2(SYS_getrusage, @bitCast(usize, @as(isize, who)), @ptrToInt(usage));
}
pub fn tcgetattr(fd: fd_t, termios_p: *termios) usize {
return syscall3(SYS_ioctl, @bitCast(usize, @as(isize, fd)), TCGETS, @ptrToInt(termios_p));
}
pub fn tcsetattr(fd: fd_t, optional_action: TCSA, termios_p: *const termios) usize {
return syscall3(SYS_ioctl, @bitCast(usize, @as(isize, fd)), TCSETS + @enumToInt(optional_action), @ptrToInt(termios_p));
}
test "" {
if (builtin.os == .linux) {
_ = @import("linux/test.zig");