From a697de3eac7fb4bb09e7f2aaee18c916a4eacc07 Mon Sep 17 00:00:00 2001 From: nofmal Date: Thu, 30 Jan 2020 13:36:28 +0700 Subject: [PATCH] Add basic linux termios implementation --- lib/std/c.zig | 2 ++ lib/std/os.zig | 32 +++++++++++++++++ lib/std/os/bits/linux.zig | 74 +++++++++++++++++++++++++++++++++++++++ lib/std/os/linux.zig | 8 +++++ 4 files changed, 116 insertions(+) diff --git a/lib/std/c.zig b/lib/std/c.zig index 4d5e72f502..e0d292f99b 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -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; diff --git a/lib/std/os.zig b/lib/std/os.zig index a9c4a49f1f..302d8bfce5 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -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), + } + } +} diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig index b8e8c33bee..e0fc5561f2 100644 --- a/lib/std/os/bits/linux.zig +++ b/lib/std/os/bits/linux.zig @@ -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, +}; diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 5c25b4369c..d11f206482 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -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");