-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathxauth.zig
124 lines (111 loc) · 3.81 KB
/
xauth.zig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
const std = @import("std");
const x = @import("x.zig");
const global = struct {
pub var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
pub const arena = arena_instance.allocator();
};
const Opt = struct {
auth_filename: ?[]const u8 = null,
};
fn usage() void {
std.debug.print(
\\usage: xauth [-options ...] [command arg ...]
\\
\\OPTIONS:
\\ -f authfilename Authorization file to use. Optional, defaults to $XAUTHORITY or $HOME/.Xauthority
\\
\\COMMANDS:
\\ help Print help
\\ list List authorization entries
\\
, .{});
}
pub fn main() !void {
const all_args = try std.process.argsAlloc(global.arena);
// no need to free
var opt = Opt{};
const args = blk: {
var new_arg_count: usize = 0;
var arg_index: usize = 1;
while (arg_index < all_args.len) : (arg_index += 1) {
const arg = all_args[arg_index];
if (!std.mem.startsWith(u8, arg, "-")) {
all_args[new_arg_count] = arg;
new_arg_count += 1;
} else if (std.mem.eql(u8, arg, "-f")) {
arg_index += 1;
if (arg_index >= all_args.len) {
std.log.err("missing authfilename after option -f", .{});
std.process.exit(1);
}
opt.auth_filename = all_args[arg_index];
} else {
std.log.err("invalid option \"{s}\"", .{arg});
std.process.exit(1);
}
}
break :blk all_args[0..new_arg_count];
};
if (args.len == 0) {
usage();
return;
}
const cmd = args[0];
const cmd_args = args[1..];
if (std.mem.eql(u8, cmd, "help")) {
usage();
} else if (std.mem.eql(u8, cmd, "list")) {
try list(opt, cmd_args);
} else {
std.log.err("invalid command \"{s}\"", .{cmd});
std.process.exit(1);
}
}
fn list(opt: Opt, cmd_args: []const [:0]const u8) !void {
if (cmd_args.len != 0) {
std.log.err("list command doesn't accept any arguments", .{});
std.process.exit(1);
}
const auth_filename = blk: {
if (opt.auth_filename) |f| break :blk x.AuthFilename{
.str = f,
.owned = false,
};
break :blk try x.getAuthFilename(global.arena) orelse {
std.log.err("unable to find an Xauthority file", .{});
std.process.exit(1);
};
};
// no need to auth_filename.deinit(allocator);
const auth_mapped = try x.MappedFile.init(auth_filename.str, .{});
defer auth_mapped.unmap();
const stdout_writer = std.io.getStdOut().writer();
var buffered_writer = std.io.bufferedWriter(stdout_writer);
const writer = buffered_writer.writer();
var auth_it = x.AuthIterator{ .mem = auth_mapped.mem };
while (auth_it.next() catch {
std.log.err("auth file '{s}' is invalid", .{auth_filename.str});
std.process.exit(1);
}) |entry| {
switch (entry.family) {
.wild => {}, // not sure what to do, should we write "*"? nothing?
else => {
const addr = x.Addr{
.family = entry.family,
.data = entry.addr(auth_mapped.mem),
};
try addr.format("", .{}, writer);
},
}
var display_buf: [40]u8 = undefined;
const display: []const u8 = if (entry.display_num) |d| (
std.fmt.bufPrint(&display_buf, "{}", .{d}) catch unreachable
) else "";
try writer.print(":{s} {s} {}\n", .{
display,
entry.name(auth_mapped.mem),
std.fmt.fmtSliceHexLower(entry.data(auth_mapped.mem)),
});
}
try buffered_writer.flush();
}