lens

posix system fetch tool
git clone git://brookjeynes.dev/bjeynes/lens.git
Log | Files | Refs | README

sys_info.zig (7797B)


      1 const std = @import("std");
      2 const builtin = @import("builtin");
      3 
      4 const process = @import("process.zig");
      5 
      6 pub fn getCpu(io: std.Io, allocator: std.mem.Allocator) ![]const u8 {
      7     switch (builtin.os.tag) {
      8         .linux, .openbsd => {
      9             const file = try std.Io.Dir.openFileAbsolute(
     10                 io,
     11                 "/proc/cpuinfo",
     12                 .{ .mode = .read_only },
     13             );
     14             defer file.close(io);
     15 
     16             var file_buffer: [1024]u8 = undefined;
     17             var file_reader = file.reader(io, &file_buffer);
     18 
     19             while (try file_reader.interface.takeDelimiter('\n')) |line| {
     20                 if (std.mem.startsWith(u8, line, "model name")) {
     21                     var name_it = std.mem.tokenizeScalar(u8, line, ':');
     22                     _ = name_it.next(); // Skip "model name :"
     23                     const name = name_it.next() orelse return error.ModelNameIsNull;
     24 
     25                     return try allocator.dupe(u8, std.mem.trim(u8, name, " \t"));
     26                 }
     27             }
     28 
     29             return error.ModelNameIsNotSpecified;
     30         },
     31         // TODO: upgrade to 0.16.0
     32         // .macos => {
     33         //     const child = try std.process.Child.run(.{
     34         //         .allocator = allocator,
     35         //         .argv = &[_][]const u8{ "sysctl", "-n", "machdep.cpu.brand_string" },
     36         //     });
     37         //     defer allocator.free(child.stderr);
     38         //
     39         //     if (child.term.Exited != 0) {
     40         //         return error.FailedToReadMacCPU;
     41         //     }
     42         //
     43         //     return child.stdout;
     44         // },
     45         else => return error.UnsupportedOs,
     46     }
     47 }
     48 
     49 pub fn getShell(io: std.Io, allocator: std.mem.Allocator, env_map: *std.process.Environ.Map) ![]const u8 {
     50     if (builtin.os.tag != .linux and builtin.os.tag != .openbsd) return error.UnsupportedOs;
     51 
     52     if (env_map.get("SHELL")) |shell_path| {
     53         var shell_it = std.mem.tokenizeScalar(u8, shell_path, '/');
     54         var shell: []const u8 = undefined;
     55         // Get the last element
     56         while (shell_it.next()) |split| {
     57             shell = split;
     58         }
     59 
     60         return try allocator.dupe(u8, shell);
     61     }
     62 
     63     // If $SHELL is not set, try find the shell via pid.
     64     // Walk up the process tree: current -> parent -> grandparent
     65     const parent_info = try process.getProcessInfo(io, allocator, std.os.linux.getppid());
     66     defer allocator.free(parent_info.name);
     67 
     68     const grandparent_info = try process.getProcessInfo(io, allocator, parent_info.ppid);
     69     return grandparent_info.name;
     70 }
     71 
     72 pub fn getDesktop(allocator: std.mem.Allocator, env_map: *std.process.Environ.Map) ![]const u8 {
     73     if (builtin.os.tag != .linux and builtin.os.tag != .openbsd) return error.UnsupportedOs;
     74 
     75     if (env_map.get("XDG_CURRENT_DESKTOP")) |desktop| {
     76         return try allocator.dupe(u8, desktop);
     77     }
     78 
     79     if (env_map.get("XDG_SESSION_DESKTOP")) |desktop| {
     80         return try allocator.dupe(u8, desktop);
     81     }
     82 
     83     if (env_map.get("DESKTOP_SESSION")) |desktop| {
     84         return try allocator.dupe(u8, desktop);
     85     }
     86 
     87     if (env_map.get("XDG_SESSION_TYPE")) |session_type| {
     88         if (std.mem.eql(u8, session_type, "tty")) {
     89             return try allocator.dupe(u8, "Headless");
     90         }
     91     }
     92 
     93     return try allocator.dupe(u8, "Unknown");
     94 }
     95 
     96 pub fn getDistro(io: std.Io, allocator: std.mem.Allocator) ![]const u8 {
     97     switch (builtin.os.tag) {
     98         .linux, .openbsd => {
     99             const utsname = std.posix.uname();
    100 
    101             const file = try std.Io.Dir.openFileAbsolute(
    102                 io,
    103                 "/etc/os-release",
    104                 .{ .mode = .read_only },
    105             );
    106             defer file.close(io);
    107 
    108             var file_buffer: [1024]u8 = undefined;
    109             var file_reader = file.reader(io, &file_buffer);
    110 
    111             while (try file_reader.interface.takeDelimiter('\n')) |line| {
    112                 if (std.mem.startsWith(u8, line, "PRETTY_NAME")) {
    113                     var name_it = std.mem.tokenizeScalar(u8, line, '=');
    114                     _ = name_it.next(); // Skip "NAME="
    115                     const name = name_it.next() orelse return error.OsIdIsNull;
    116 
    117                     var name_machine_buf: [1024]u8 = undefined;
    118                     const name_machine = try std.fmt.bufPrint(
    119                         &name_machine_buf,
    120                         "{s} {s}",
    121                         .{ std.mem.trim(u8, name, "\""), std.mem.sliceTo(&utsname.machine, 0) },
    122                     );
    123                     return try allocator.dupe(u8, name_machine);
    124                 }
    125             }
    126 
    127             return error.OsIdNotSpecified;
    128         },
    129         .macos => {
    130             const utsname = std.posix.uname();
    131 
    132             var name_machine_buf: [1024]u8 = undefined;
    133             const name_machine = try std.fmt.bufPrint(
    134                 &name_machine_buf,
    135                 "MacOS X {s}",
    136                 .{std.mem.sliceTo(&utsname.machine, 0)},
    137             );
    138             return try allocator.dupe(u8, name_machine);
    139         },
    140         else => return error.UnsupportedOs,
    141     }
    142 }
    143 
    144 pub fn getDistroId(io: std.Io, allocator: std.mem.Allocator) ![]const u8 {
    145     switch (builtin.os.tag) {
    146         .linux, .openbsd => {
    147             const file = try std.Io.Dir.openFileAbsolute(
    148                 io,
    149                 "/etc/os-release",
    150                 .{ .mode = .read_only },
    151             );
    152             defer file.close(io);
    153 
    154             var file_buffer: [1024]u8 = undefined;
    155             var file_reader = file.reader(io, &file_buffer);
    156 
    157             while (try file_reader.interface.takeDelimiter('\n')) |line| {
    158                 if (std.mem.startsWith(u8, line, "ID")) {
    159                     var id_it = std.mem.tokenizeScalar(u8, line, '=');
    160                     _ = id_it.next(); // Skip "ID="
    161                     const id = id_it.next() orelse return error.OsIdIsNull;
    162                     return try allocator.dupe(u8, id);
    163                 }
    164             }
    165 
    166             return error.OsIdNotSpecified;
    167         },
    168         .macos => {
    169             const utsname = std.posix.uname();
    170             return try allocator.dupe(u8, std.mem.sliceTo(&utsname.nodename, 0));
    171         },
    172         else => return error.UnsupportedOs,
    173     }
    174 }
    175 
    176 pub fn getUser(allocator: std.mem.Allocator, env_map: *std.process.Environ.Map) ![]const u8 {
    177     const user_env = env_map.get("USER") orelse return error.USEREnvNotSet;
    178     return try allocator.dupe(u8, user_env);
    179 }
    180 
    181 pub fn getDisk(io: std.Io, allocator: std.mem.Allocator) ![]const u8 {
    182     if (builtin.os.tag != .linux and builtin.os.tag != .openbsd) return error.UnsupportedOs;
    183 
    184     const child = try std.process.run(allocator, io, .{
    185         .argv = &[_][]const u8{ "df", "-h", "--output=size,used,pcent", "/" },
    186     });
    187     defer allocator.free(child.stdout);
    188     defer allocator.free(child.stderr);
    189 
    190     if (child.term.exited != 0) {
    191         return error.FailedToReadMacCPU;
    192     }
    193 
    194     var output_it = std.mem.tokenizeScalar(u8, child.stdout, '\n');
    195     _ = output_it.next(); // Skip headers.
    196 
    197     const line = std.mem.trim(
    198         u8,
    199         output_it.next() orelse return error.DiskUsageIsNull,
    200         " ",
    201     );
    202 
    203     var line_it = std.mem.tokenizeScalar(u8, line, ' ');
    204 
    205     const total = std.mem.trim(
    206         u8,
    207         line_it.next() orelse return error.DiskTotalIsNull,
    208         " ",
    209     );
    210     const used = std.mem.trim(
    211         u8,
    212         line_it.next() orelse return error.DiskUsedIsNull,
    213         " ",
    214     );
    215     const percentage = std.mem.trim(
    216         u8,
    217         line_it.next() orelse return error.DiskPercentageIsNull,
    218         " ",
    219     );
    220 
    221     var output_buf: [1024]u8 = undefined;
    222     const output = try std.fmt.bufPrint(
    223         &output_buf,
    224         "{s} / {s} ({s})",
    225         .{ used, total, percentage },
    226     );
    227     return try allocator.dupe(u8, output);
    228 }