Make print_clogs
only print clogs
Externalize matching functionality between user port spec and found clogs (socket + process information).
This commit is contained in:
parent
85f097eb3b
commit
37f51c6002
4 changed files with 160 additions and 78 deletions
138
src/main.zig
138
src/main.zig
|
@ -2,6 +2,7 @@ const std = @import("std");
|
|||
const builtin = @import("builtin");
|
||||
const sockets = @import("sockets.zig");
|
||||
const process = @import("process.zig");
|
||||
const match = @import("match.zig");
|
||||
const c = @cImport({
|
||||
@cInclude("pwd.h");
|
||||
@cInclude("arpa/inet.h");
|
||||
|
@ -26,16 +27,19 @@ pub fn main() !u8 {
|
|||
};
|
||||
defer alloc.free(ports);
|
||||
|
||||
const pids = try print_clogs(alloc, ports);
|
||||
defer alloc.free(pids);
|
||||
const clogs = try match.match(alloc, ports);
|
||||
defer clogs.deinit();
|
||||
|
||||
if (pids.len == 0) {
|
||||
if (clogs.items.len == 0) {
|
||||
try std.io.getStdOut().writeAll("Ports look unclogged\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
try print_clogs(clogs);
|
||||
|
||||
var kills: []u16 = undefined;
|
||||
while(true) {
|
||||
kills = choose_kill(alloc, pids.len) catch |err| {
|
||||
kills = choose_kill(alloc, clogs.items.len) catch |err| {
|
||||
if (builtin.mode == std.builtin.Mode.Debug) {
|
||||
try kill_usage();
|
||||
return err;
|
||||
|
@ -49,7 +53,16 @@ pub fn main() !u8 {
|
|||
defer alloc.free(kills);
|
||||
|
||||
for(kills) |k| {
|
||||
kill(pids[k-1]);
|
||||
// go find the kill
|
||||
var procnum: usize = 0;
|
||||
for(clogs.items) |clog| {
|
||||
if(clog.procs.items.len < (k-procnum)) { // kill is in a process in the next clog
|
||||
procnum += clog.procs.items.len;
|
||||
} else { // kill is in this clog - the # of clog process we passed
|
||||
kill(clog.procs.items[k-procnum-1].pid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -125,85 +138,60 @@ fn choose_kill(alloc: std.mem.Allocator, choices: usize) ![]u16 {
|
|||
return kills;
|
||||
}
|
||||
|
||||
fn print_clogs(alloc: std.mem.Allocator, ports: []u16) ![]std.posix.pid_t {
|
||||
fn print_clogs(clogs: match.Clogs) !void {
|
||||
var writer = std.io.getStdOut().writer();
|
||||
var pids = std.ArrayList(std.posix.pid_t).init(alloc);
|
||||
defer pids.deinit(); // noop after re-owning memory at end
|
||||
|
||||
const clog_sockets = try sockets.parse(alloc, null);
|
||||
defer alloc.free(clog_sockets);
|
||||
|
||||
var any: bool = false;
|
||||
for (clog_sockets) |cs| {
|
||||
if(std.mem.indexOfScalar(u16, ports, cs.port)) |_| {
|
||||
any = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!any) {
|
||||
try writer.writeAll("Ports look unclogged\n");
|
||||
return &[_]std.posix.pid_t{};
|
||||
}
|
||||
|
||||
try writer.print("{s: <3}{s: <10} {s: <30} {s: <12} {s: <15} {s: <10} {s: <6} {s: <5}\n", .{ "#", "Command", "Path", "Protocol", "Address", "User", "Inode", "Port" });
|
||||
var idx: usize = 1;
|
||||
|
||||
for (clog_sockets) |cs| {
|
||||
if (std.mem.indexOfScalar(u16, ports, cs.port)) |_| {
|
||||
const clogs = try process.find_by_inode(alloc, cs.inode, null);
|
||||
defer clogs.deinit();
|
||||
for (clogs.items) |clog| {
|
||||
const user = c.getpwuid(clog.sock.uid);
|
||||
|
||||
const user = c.getpwuid(cs.uid);
|
||||
|
||||
for (clogs.items) |clog| {
|
||||
switch (cs.protocol_data) {
|
||||
// zig fmt: off
|
||||
.tcp_v4 => |proto| {
|
||||
var addr: [c.INET_ADDRSTRLEN:0]u8 = undefined;
|
||||
_ = c.inet_ntop(c.AF_INET, &proto.addr, &addr, c.INET_ADDRSTRLEN);
|
||||
try writer.print("{d: <3}{s: <10} {s: <30} {s: <12} {s: <15} {s: <10} {d: <6} {d: <5}\n", .{
|
||||
idx,
|
||||
clog.comm[0..@min(10, clog.comm.len)], clog.exe[0..@min(30, clog.exe.len)],
|
||||
"TCP/IPv4", std.mem.sliceTo(&addr, 0),
|
||||
user.*.pw_name, cs.inode, cs.port });
|
||||
},
|
||||
.tcp_v6 => |proto| {
|
||||
var addr: [c.INET6_ADDRSTRLEN:0]u8 = undefined;
|
||||
_ = c.inet_ntop(c.AF_INET6, &proto.addr, &addr, c.INET6_ADDRSTRLEN);
|
||||
try writer.print("{d: <3}{s: <10} {s: <30} {s: <12} {s: <15} {s: <10} {d: <6} {d: <5}\n", .{
|
||||
idx,
|
||||
clog.comm[0..@min(10, clog.comm.len)], clog.exe[0..@min(30, clog.exe.len)],
|
||||
"TCP/IPv6", std.mem.sliceTo(&addr, 0),
|
||||
user.*.pw_name, cs.inode, cs.port });
|
||||
},
|
||||
.udp_v4 => |proto| {
|
||||
var addr: [c.INET_ADDRSTRLEN:0]u8 = undefined;
|
||||
_ = c.inet_ntop(c.AF_INET, &proto.addr, &addr, c.INET_ADDRSTRLEN);
|
||||
try writer.print("{d: <3}{s: <10} {s: <30} {s: <12} {s: <15} {s: <10} {d: <6} {d: <5}\n", .{
|
||||
idx,
|
||||
clog.comm[0..@min(10, clog.comm.len)], clog.exe[0..@min(30, clog.exe.len)],
|
||||
"UDP/IPv4", std.mem.sliceTo(&addr, 0),
|
||||
user.*.pw_name, cs.inode, cs.port });
|
||||
},
|
||||
.udp_v6 => |proto| {
|
||||
var addr: [c.INET6_ADDRSTRLEN:0]u8 = undefined;
|
||||
_ = c.inet_ntop(c.AF_INET6, &proto.addr, &addr, c.INET6_ADDRSTRLEN);
|
||||
try writer.print("{d: <3}{s: <10} {s: <30} {s: <12} {s: <15} {s: <10} {d: <6} {d: <5}\n", .{
|
||||
idx,
|
||||
clog.comm[0..@min(10, clog.comm.len)], clog.exe[0..@min(30, clog.exe.len)],
|
||||
"UDP/IPv6", std.mem.sliceTo(&addr, 0),
|
||||
user.*.pw_name, cs.inode, cs.port });
|
||||
},
|
||||
// zig fmt: on
|
||||
}
|
||||
|
||||
try pids.append(clog.pid);
|
||||
idx += 1;
|
||||
for (clog.procs.items) |proc| {
|
||||
switch (clog.sock.protocol_data) {
|
||||
// zig fmt: off
|
||||
.tcp_v4 => |proto| {
|
||||
var addr: [c.INET_ADDRSTRLEN:0]u8 = undefined;
|
||||
_ = c.inet_ntop(c.AF_INET, &proto.addr, &addr, c.INET_ADDRSTRLEN);
|
||||
try writer.print("{d: <3}{s: <10} {s: <30} {s: <12} {s: <15} {s: <10} {d: <6} {d: <5}\n", .{
|
||||
idx,
|
||||
proc.comm[0..@min(10, proc.comm.len)], proc.exe[0..@min(30, proc.exe.len)],
|
||||
"TCP/IPv4", std.mem.sliceTo(&addr, 0),
|
||||
user.*.pw_name, clog.sock.inode, clog.port });
|
||||
},
|
||||
.tcp_v6 => |proto| {
|
||||
var addr: [c.INET6_ADDRSTRLEN:0]u8 = undefined;
|
||||
_ = c.inet_ntop(c.AF_INET6, &proto.addr, &addr, c.INET6_ADDRSTRLEN);
|
||||
try writer.print("{d: <3}{s: <10} {s: <30} {s: <12} {s: <15} {s: <10} {d: <6} {d: <5}\n", .{
|
||||
idx,
|
||||
proc.comm[0..@min(10, proc.comm.len)], proc.exe[0..@min(30, proc.exe.len)],
|
||||
"TCP/IPv6", std.mem.sliceTo(&addr, 0),
|
||||
user.*.pw_name, clog.sock.inode, clog.port });
|
||||
},
|
||||
.udp_v4 => |proto| {
|
||||
var addr: [c.INET_ADDRSTRLEN:0]u8 = undefined;
|
||||
_ = c.inet_ntop(c.AF_INET, &proto.addr, &addr, c.INET_ADDRSTRLEN);
|
||||
try writer.print("{d: <3}{s: <10} {s: <30} {s: <12} {s: <15} {s: <10} {d: <6} {d: <5}\n", .{
|
||||
idx,
|
||||
proc.comm[0..@min(10, proc.comm.len)], proc.exe[0..@min(30, proc.exe.len)],
|
||||
"UDP/IPv4", std.mem.sliceTo(&addr, 0),
|
||||
user.*.pw_name, clog.sock.inode, clog.port });
|
||||
},
|
||||
.udp_v6 => |proto| {
|
||||
var addr: [c.INET6_ADDRSTRLEN:0]u8 = undefined;
|
||||
_ = c.inet_ntop(c.AF_INET6, &proto.addr, &addr, c.INET6_ADDRSTRLEN);
|
||||
try writer.print("{d: <3}{s: <10} {s: <30} {s: <12} {s: <15} {s: <10} {d: <6} {d: <5}\n", .{
|
||||
idx,
|
||||
proc.comm[0..@min(10, proc.comm.len)], proc.exe[0..@min(30, proc.exe.len)],
|
||||
"UDP/IPv6", std.mem.sliceTo(&addr, 0),
|
||||
user.*.pw_name, clog.sock.inode, clog.port });
|
||||
},
|
||||
// zig fmt: on
|
||||
}
|
||||
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return pids.toOwnedSlice();
|
||||
}
|
||||
|
||||
fn usage() !void {
|
||||
|
|
55
src/match.zig
Normal file
55
src/match.zig
Normal file
|
@ -0,0 +1,55 @@
|
|||
const std = @import("std");
|
||||
const process = @import("process.zig");
|
||||
const sockets = @import("sockets.zig");
|
||||
|
||||
pub const Clogs = struct {
|
||||
items: []Clog,
|
||||
alloc: std.mem.Allocator,
|
||||
|
||||
pub fn deinit(self: @This()) void {
|
||||
for(self.items) |clog| {
|
||||
clog.deinit();
|
||||
}
|
||||
|
||||
self.alloc.free(self.items);
|
||||
}
|
||||
};
|
||||
|
||||
pub const Clog = struct {
|
||||
port: u16,
|
||||
sock: sockets.ClogSocket,
|
||||
procs: process.ClogProcesses,
|
||||
|
||||
alloc: std.mem.Allocator,
|
||||
|
||||
pub fn deinit(self: @This()) void {
|
||||
self.procs.deinit();
|
||||
}
|
||||
};
|
||||
|
||||
pub fn match(alloc: std.mem.Allocator, ports: []u16) !Clogs {
|
||||
var buf = std.ArrayList(Clog).init(alloc);
|
||||
defer(buf.deinit()); // noop after re-owned at end
|
||||
|
||||
const socks = try sockets.parse(alloc, null);
|
||||
defer alloc.free(socks);
|
||||
|
||||
for (socks) |sock| {
|
||||
if (std.mem.indexOfScalar(u16, ports, sock.port) == null) continue;
|
||||
|
||||
const procs = try process.find_by_inode(alloc, sock.inode, null);
|
||||
defer procs.deinit();
|
||||
|
||||
try buf.append(Clog {
|
||||
.port = sock.port,
|
||||
.sock = sock.clone(),
|
||||
.procs = try procs.clone(alloc),
|
||||
.alloc = alloc,
|
||||
});
|
||||
}
|
||||
|
||||
return Clogs{
|
||||
.items = try buf.toOwnedSlice(),
|
||||
.alloc = alloc,
|
||||
};
|
||||
}
|
|
@ -6,7 +6,7 @@ const std = @import("std");
|
|||
/// handling deallocation correctly. Call `deinit` to deallocate the memory.
|
||||
///
|
||||
/// Processes can be accessed via `.items`
|
||||
pub const Clogs = struct {
|
||||
pub const ClogProcesses = struct {
|
||||
items: []ClogProcess,
|
||||
alloc: std.mem.Allocator,
|
||||
|
||||
|
@ -14,6 +14,18 @@ pub const Clogs = struct {
|
|||
try writer.print("{any}", .{value.items});
|
||||
}
|
||||
|
||||
pub fn clone(self: @This(), alloc: std.mem.Allocator) !ClogProcesses {
|
||||
var items = try alloc.alloc(ClogProcess, self.items.len);
|
||||
for(self.items, 0..) |item, idx| {
|
||||
items[idx] = try item.clone(alloc);
|
||||
}
|
||||
|
||||
return ClogProcesses {
|
||||
.items = items,
|
||||
.alloc = alloc
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: @This()) void {
|
||||
for (self.items) |item| {
|
||||
item.deinit();
|
||||
|
@ -44,6 +56,24 @@ pub const ClogProcess = struct {
|
|||
try writer.writeAll("}");
|
||||
}
|
||||
|
||||
pub fn clone(self: @This(), alloc: std.mem.Allocator) !ClogProcess {
|
||||
var cmdline: [][]u8 = try alloc.alloc([]u8, self.cmdline.len);
|
||||
for(self.cmdline, 0..) |line, idx| {
|
||||
cmdline[idx] = try alloc.dupe(u8, line);
|
||||
}
|
||||
|
||||
return ClogProcess {
|
||||
.pid = self.pid,
|
||||
.inode = self.inode,
|
||||
.fd = self.fd,
|
||||
.comm = try alloc.dupe(u8, self.comm),
|
||||
.exe = try alloc.dupe(u8, self.exe),
|
||||
.cmdline = cmdline,
|
||||
|
||||
.alloc = alloc
|
||||
};
|
||||
}
|
||||
|
||||
fn deinit(self: @This()) void {
|
||||
self.alloc.free(self.comm);
|
||||
self.alloc.free(self.exe);
|
||||
|
@ -55,7 +85,7 @@ pub const ClogProcess = struct {
|
|||
};
|
||||
|
||||
/// Find clogging processes that hold a file handle on an inode
|
||||
pub fn find_by_inode(alloc: std.mem.Allocator, inode: std.posix.ino_t, proc_path: ?[]const u8) !Clogs {
|
||||
pub fn find_by_inode(alloc: std.mem.Allocator, inode: std.posix.ino_t, proc_path: ?[]const u8) !ClogProcesses {
|
||||
const base = proc_path orelse "/proc";
|
||||
|
||||
var clogs = std.ArrayList(ClogProcess).init(alloc);
|
||||
|
@ -112,7 +142,7 @@ pub fn find_by_inode(alloc: std.mem.Allocator, inode: std.posix.ino_t, proc_path
|
|||
}
|
||||
}
|
||||
|
||||
return Clogs{ .items = try clogs.toOwnedSlice(), .alloc = alloc };
|
||||
return ClogProcesses{ .items = try clogs.toOwnedSlice(), .alloc = alloc };
|
||||
}
|
||||
|
||||
const ProcessFileData = struct {
|
||||
|
|
|
@ -11,6 +11,15 @@ pub const ClogSocket = struct {
|
|||
inode: std.posix.ino_t,
|
||||
uid: std.posix.uid_t,
|
||||
protocol_data: ProtocolData,
|
||||
|
||||
pub fn clone(self: @This()) ClogSocket {
|
||||
return ClogSocket {
|
||||
.port = self.port,
|
||||
.inode = self.inode,
|
||||
.uid = self.uid,
|
||||
.protocol_data = self.protocol_data
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Known protocols
|
||||
|
|
Loading…
Reference in a new issue