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 }