mirror of
https://mzte.de/git/LordMZTE/dotfiles.git
synced 2024-09-27 12:38:58 +02:00
optimize openbrowser process scanning
This commit is contained in:
parent
5b9ceb34b5
commit
47d6d3b579
3 changed files with 80 additions and 76 deletions
|
@ -1,67 +0,0 @@
|
||||||
const std = @import("std");
|
|
||||||
|
|
||||||
running: bool,
|
|
||||||
exepath: ?[]const u8,
|
|
||||||
|
|
||||||
const Self = @This();
|
|
||||||
|
|
||||||
/// Frees the data of this ProcessInfo.
|
|
||||||
/// `alloc` must be the same allocator that was supplied to `get`!
|
|
||||||
pub fn deinit(self: *Self, alloc: std.mem.Allocator) void {
|
|
||||||
if (self.exepath) |exepath|
|
|
||||||
alloc.free(exepath);
|
|
||||||
self.* = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets information about a process given it's name
|
|
||||||
pub fn get(
|
|
||||||
name: []const u8,
|
|
||||||
alloc: std.mem.Allocator,
|
|
||||||
) !Self {
|
|
||||||
var proc_dir = try std.fs.openIterableDirAbsolute("/proc", .{});
|
|
||||||
defer proc_dir.close();
|
|
||||||
|
|
||||||
var proc_iter = proc_dir.iterate();
|
|
||||||
procs: while (try proc_iter.next()) |proc| {
|
|
||||||
// Filter directories that aren't PIDs
|
|
||||||
for (std.fs.path.basename(proc.name)) |letter|
|
|
||||||
if (!std.ascii.isDigit(letter))
|
|
||||||
continue :procs;
|
|
||||||
|
|
||||||
var buf: [512]u8 = undefined;
|
|
||||||
const cmdline_f = std.fs.openFileAbsolute(
|
|
||||||
try std.fmt.bufPrint(&buf, "/proc/{s}/cmdline", .{proc.name}),
|
|
||||||
.{},
|
|
||||||
) catch |e| {
|
|
||||||
// This just happens when we're dealing with another user's process.
|
|
||||||
if (e == error.AccessDenied)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
return e;
|
|
||||||
};
|
|
||||||
|
|
||||||
defer cmdline_f.close();
|
|
||||||
|
|
||||||
const cmdline_data = try cmdline_f.readToEndAlloc(alloc, std.math.maxInt(usize));
|
|
||||||
defer alloc.free(cmdline_data);
|
|
||||||
|
|
||||||
var cmdline_splits = std.mem.split(u8, cmdline_data, &.{0});
|
|
||||||
const exepath = cmdline_splits.next() orelse return error.InvalidCmdline;
|
|
||||||
|
|
||||||
// this is a startsWith instead of an eql because the arguments in the
|
|
||||||
// cmdline file are sometimes (and only sometimes!) separated by spaces
|
|
||||||
// and not null bytes.
|
|
||||||
if (!std.mem.startsWith(u8, std.fs.path.basename(exepath), name))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
return .{
|
|
||||||
.running = true,
|
|
||||||
.exepath = try alloc.dupe(u8, exepath),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return .{
|
|
||||||
.running = false,
|
|
||||||
.exepath = null,
|
|
||||||
};
|
|
||||||
}
|
|
68
scripts/openbrowser/src/info.zig
Normal file
68
scripts/openbrowser/src/info.zig
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub const ProcessQuery = struct {
|
||||||
|
name: []const u8,
|
||||||
|
found_exepath: ?[]const u8 = null,
|
||||||
|
|
||||||
|
pub fn deinit(self: *ProcessQuery, alloc: std.mem.Allocator) void {
|
||||||
|
if (self.found_exepath) |p|
|
||||||
|
alloc.free(p);
|
||||||
|
|
||||||
|
self.* = undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn query(alloc: std.mem.Allocator, queries: []ProcessQuery) !void {
|
||||||
|
var proc_dir = try std.fs.openIterableDirAbsolute("/proc", .{});
|
||||||
|
defer proc_dir.close();
|
||||||
|
|
||||||
|
var proc_iter = proc_dir.iterate();
|
||||||
|
procs: while (try proc_iter.next()) |proc| {
|
||||||
|
// only look at directories which represent PIDs
|
||||||
|
for (std.fs.path.basename(proc.name)) |c|
|
||||||
|
if (!std.ascii.isDigit(c))
|
||||||
|
continue :procs;
|
||||||
|
|
||||||
|
var buf: [std.fs.MAX_PATH_BYTES]u8 = undefined;
|
||||||
|
const cmdline_f = std.fs.openFileAbsolute(
|
||||||
|
try std.fmt.bufPrint(&buf, "/proc/{s}/cmdline", .{proc.name}),
|
||||||
|
.{},
|
||||||
|
) catch |e| switch (e) {
|
||||||
|
// skip other users' processes
|
||||||
|
error.AccessDenied => continue,
|
||||||
|
else => return e,
|
||||||
|
};
|
||||||
|
defer cmdline_f.close();
|
||||||
|
|
||||||
|
// read first part of null-separated data (binary path)
|
||||||
|
const exepath = epath: {
|
||||||
|
var fbs = std.io.fixedBufferStream(&buf);
|
||||||
|
cmdline_f.reader().streamUntilDelimiter(fbs.writer(), 0, null) catch |e| switch (e) {
|
||||||
|
// occurs if there's no delimiter
|
||||||
|
error.EndOfStream => {},
|
||||||
|
else => return e,
|
||||||
|
};
|
||||||
|
break :epath fbs.getWritten();
|
||||||
|
};
|
||||||
|
|
||||||
|
var found_all = true;
|
||||||
|
|
||||||
|
for (queries) |*q| {
|
||||||
|
if (q.found_exepath) |_|
|
||||||
|
continue;
|
||||||
|
|
||||||
|
found_all = false;
|
||||||
|
|
||||||
|
// this is a startsWith instead of an eql because the arguments in the
|
||||||
|
// cmdline file are sometimes (and only sometimes!) separated by spaces
|
||||||
|
// and not null bytes.
|
||||||
|
if (!std.mem.startsWith(u8, std.fs.path.basename(exepath), q.name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
q.found_exepath = try alloc.dupe(u8, exepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found_all)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const ProcessInfo = @import("ProcessInfo.zig");
|
const info = @import("info.zig");
|
||||||
|
|
||||||
pub const std_options = struct {
|
pub const std_options = struct {
|
||||||
pub const log_level = .debug;
|
pub const log_level = .debug;
|
||||||
|
@ -16,18 +16,21 @@ pub fn main() !void {
|
||||||
defer _ = gpa.deinit();
|
defer _ = gpa.deinit();
|
||||||
const alloc = gpa.allocator();
|
const alloc = gpa.allocator();
|
||||||
|
|
||||||
for (browsers) |browser| {
|
var queries: [browsers.len]info.ProcessQuery = undefined;
|
||||||
var info = try ProcessInfo.get(browser, alloc);
|
for (browsers, &queries) |b, *q|
|
||||||
defer info.deinit(alloc);
|
q.* = .{ .name = b };
|
||||||
|
|
||||||
if (!info.running)
|
try info.query(alloc, &queries);
|
||||||
continue;
|
defer for (&queries) |*q| q.deinit(alloc);
|
||||||
|
|
||||||
std.log.info("found running browser {s}", .{info.exepath.?});
|
for (queries) |q| {
|
||||||
|
if (q.found_exepath) |path| {
|
||||||
|
std.log.info("found running browser: {s}", .{path});
|
||||||
|
|
||||||
try start(browser, alloc);
|
try start(q.name, alloc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std.log.info("no running browser, using first choice", .{});
|
std.log.info("no running browser, using first choice", .{});
|
||||||
try start(browsers[0], alloc);
|
try start(browsers[0], alloc);
|
||||||
|
|
Loading…
Reference in a new issue