const std = @import("std"); const ArgError = error{ NotEnoughArgs, BadDomain, InvalidAddressVer, }; pub const IP_VER_ENUM = enum(u3) { IPv4 = 4, IPv6 = 6, }; pub const IPs = struct { v4: []const u8, v6: []const u8, }; pub const Domain = struct { name: [:0]const u8, labels: [5][]const u8, }; pub fn check_perms() !void { var f = try std.fs.openFileAbsolute("/etc/hosts", .{ .mode = .write_only }); f.close(); } pub fn get_input() !struct { Domain, IP_VER_ENUM, } { var args = std.process.args(); _ = args.next(); // consume calling binary arg const domain_str = args.next() orelse return ArgError.NotEnoughArgs; const domain = try check_domain(domain_str); const ip_ver_str = args.next() orelse return ArgError.NotEnoughArgs; const ip_ver = std.meta.intToEnum(IP_VER_ENUM, std.fmt.parseInt(u3, ip_ver_str, 10) catch return ArgError.InvalidAddressVer) catch return ArgError.InvalidAddressVer; return .{ domain, ip_ver }; } fn check_domain(domain_str: [:0]const u8) !Domain { var domain = Domain{ .name = domain_str, .labels = [_][]const u8{&[_]u8{}} ** 5, }; var labels = std.mem.split(u8, domain_str, "."); var last: []const u8 = ""; var i: usize = 0; while (labels.next()) |segment| { if (i >= 5) { return ArgError.BadDomain; } last = segment; domain.labels[i] = segment; i += 1; } if (domain.labels.len <= 1 or !std.mem.eql(u8, last, "local")) { return ArgError.BadDomain; } return domain; }