src/os/client_os_linux.zig
Ref: Size: 3.0 KiB History
//! Linux arm of `client_os`. Spellings only; the contract is in the root.
const std = @import("std");
const root = @import("client_os.zig");
pub fn getpid() std.posix.pid_t {
return std.os.linux.getpid();
}
pub fn peerCred(fd: std.posix.socket_t) ?root.PeerCred {
const Ucred = extern struct { pid: std.posix.pid_t, uid: std.posix.uid_t, gid: std.posix.gid_t };
var cred: Ucred = undefined;
std.posix.getsockopt(fd, std.posix.SOL.SOCKET, std.posix.SO.PEERCRED, std.mem.asBytes(&cred)) catch return null;
return .{ .uid = cred.uid, .pid = cred.pid };
}
pub fn sendNoSig(fd: std.posix.socket_t, bytes: []const u8) std.posix.SendError!usize {
return std.posix.send(fd, bytes, std.posix.MSG.NOSIGNAL);
}
pub fn sendNoSigNoWait(fd: std.posix.socket_t, bytes: []const u8) !usize {
return std.posix.send(fd, bytes, std.posix.MSG.NOSIGNAL | std.posix.MSG.DONTWAIT);
}
/// `/proc/<pid>/stat` field 4. Parsed from the LAST ')' rather than by
/// counting spaces: field 2 is the executable's name, unquoted, and a
/// program free to call itself `a b) c` is a program free to move every
/// field after it.
pub fn parentOf(pid: std.posix.pid_t) std.posix.pid_t {
var path_buf: [64]u8 = undefined;
const path = std.fmt.bufPrint(&path_buf, "/proc/{d}/stat", .{pid}) catch return 0;
var stat_buf: [512]u8 = undefined;
const f = std.fs.cwd().openFile(path, .{}) catch return 0;
defer f.close();
const n = f.read(&stat_buf) catch return 0;
const text = stat_buf[0..n];
const close = std.mem.lastIndexOfScalar(u8, text, ')') orelse return 0;
var it = std.mem.tokenizeScalar(u8, text[close + 1 ..], ' ');
_ = it.next() orelse return 0; // the run state
const ppid = it.next() orelse return 0;
return std.fmt.parseInt(std.posix.pid_t, ppid, 10) catch 0;
}
pub fn geteuid() std.posix.uid_t {
return std.os.linux.geteuid();
}
pub fn winSize(fd: std.posix.fd_t) ?std.posix.winsize {
var ws: std.posix.winsize = undefined;
if (std.os.linux.ioctl(fd, std.os.linux.T.IOCGWINSZ, @intFromPtr(&ws)) != 0) return null;
return ws;
}
pub fn setWinSize(fd: std.posix.fd_t, ws: std.posix.winsize) error{Unsupported}!void {
if (std.os.linux.ioctl(fd, std.os.linux.T.IOCSWINSZ, @intFromPtr(&ws)) != 0) return error.Unsupported;
}
pub fn openPtyPair() error{Unsupported}!root.PtyPair {
const master = std.posix.open("/dev/ptmx", .{ .ACCMODE = .RDWR }, 0) catch return error.Unsupported;
errdefer std.posix.close(master);
var unlock: c_int = 0;
if (std.os.linux.ioctl(master, std.os.linux.T.IOCSPTLCK, @intFromPtr(&unlock)) != 0) return error.Unsupported;
var idx: c_uint = 0;
if (std.os.linux.ioctl(master, std.os.linux.T.IOCGPTN, @intFromPtr(&idx)) != 0) return error.Unsupported;
var name_buf: [32]u8 = undefined;
const name = std.fmt.bufPrint(&name_buf, "/dev/pts/{d}", .{idx}) catch return error.Unsupported;
const slave = std.posix.open(name, .{ .ACCMODE = .RDWR, .NOCTTY = true }, 0) catch return error.Unsupported;
return .{ .master = master, .slave = slave };
}