-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdaemon_client.zig
More file actions
135 lines (114 loc) · 3.69 KB
/
Copy pathdaemon_client.zig
File metadata and controls
135 lines (114 loc) · 3.69 KB
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
125
126
127
128
129
130
131
132
133
134
135
// SPDX-License-Identifier: MPL-2.0
// Copyright (c) Jonathan D.A. Jewell <j.d.a.jewell@open.ac.uk>
//! Daemon Client - Unix Socket Communication
//!
//! JSON-RPC 2.0 client for communicating with the BEAM daemon.
//! Handles complex operations: undo, redo, history, obliterate, cp, mv
const std = @import("std");
const fs = std.fs;
const mem = std.mem;
const posix = std.posix;
/// Default daemon socket path
pub const SOCKET_PATH = "/tmp/vsh-daemon.sock";
/// Check if daemon is running by testing socket accessibility
pub fn isDaemonRunning() bool {
// Check if socket file exists
fs.cwd().access(SOCKET_PATH, .{}) catch {
return false;
};
// Try to connect to verify daemon is actually listening
const socket_fd = posix.socket(posix.AF.UNIX, posix.SOCK.STREAM, 0) catch {
return false;
};
defer posix.close(socket_fd);
var addr: posix.sockaddr.un = undefined;
addr.family = posix.AF.UNIX;
// Copy socket path
const path_bytes = SOCKET_PATH;
@memcpy(addr.path[0..path_bytes.len], path_bytes);
addr.path[path_bytes.len] = 0;
// Try to connect
posix.connect(socket_fd, @ptrCast(&addr), @sizeOf(posix.sockaddr.un)) catch {
return false;
};
return true;
}
/// Print daemon not running message
pub fn printDaemonNotRunning(cmd: []const u8) !void {
const stderr = std.io.getStdErr().writer();
try stderr.print(
\\vsh: '{s}' requires BEAM daemon
\\
\\The VSH daemon provides:
\\ - Undo/redo functionality
\\ - Operation history
\\ - Transaction support
\\ - Secure deletion (obliterate)
\\
\\Start the daemon:
\\ cd impl/elixir && mix vsh.daemon start
\\
\\Or run in foreground:
\\ cd impl/elixir && iex -S mix
\\ iex> VSH.Daemon.start_link()
\\
, .{cmd});
}
/// Send a simple request to the daemon and get response
/// Returns true on success, false on failure
pub fn sendSimpleRequest(
allocator: mem.Allocator,
method: []const u8,
path: ?[]const u8,
) !bool {
_ = allocator;
const socket_fd = posix.socket(posix.AF.UNIX, posix.SOCK.STREAM, 0) catch {
return false;
};
defer posix.close(socket_fd);
var addr: posix.sockaddr.un = undefined;
addr.family = posix.AF.UNIX;
const path_bytes = SOCKET_PATH;
@memcpy(addr.path[0..path_bytes.len], path_bytes);
addr.path[path_bytes.len] = 0;
posix.connect(socket_fd, @ptrCast(&addr), @sizeOf(posix.sockaddr.un)) catch {
return false;
};
// Build simple JSON-RPC request
var buf: [4096]u8 = undefined;
var fbs = std.io.fixedBufferStream(&buf);
const writer = fbs.writer();
if (path) |p| {
try writer.print(
\\{{"jsonrpc":"2.0","method":"{s}","params":{{"path":"{s}"}},"id":1}}
\\
, .{ method, p });
} else {
try writer.print(
\\{{"jsonrpc":"2.0","method":"{s}","params":{{}},"id":1}}
\\
, .{method});
}
const request = fbs.getWritten();
// Send request
_ = posix.write(socket_fd, request) catch {
return false;
};
// Read response
var response_buf: [65536]u8 = undefined;
const bytes_read = posix.read(socket_fd, &response_buf) catch {
return false;
};
if (bytes_read == 0) {
return false;
}
// Check for success (simple check for "result" in response)
const response = response_buf[0..bytes_read];
return mem.indexOf(u8, response, "\"result\"") != null;
}
// Tests
test "isDaemonRunning returns value without crashing" {
// This test just ensures the function doesn't crash
const running = isDaemonRunning();
_ = running;
}