summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Andreas Benkard <code@mail.matthias.benkard.de>2025-08-14 17:02:19 +0200
committerMatthias Andreas Benkard <code@mail.matthias.benkard.de>2025-08-14 17:02:19 +0200
commit35a3b9ccfeb9dcd2c88c359108305b7f750622d6 (patch)
treeedb81a2398cf239741c5501a6135b35750054c03
parent63f7353b630c3eb5a6c60118418923b4b358e670 (diff)
Add pipe handling.
It is still buggy when combined with redirections, but it is a start (and I do not know whether combining pipes with redirections is supported by COMMAND.COM in the first place and what the semantics are if so).
-rw-r--r--src/cmd.zig6
-rw-r--r--src/cmd/pipe.zig44
-rw-r--r--src/eval.zig10
3 files changed, 48 insertions, 12 deletions
diff --git a/src/cmd.zig b/src/cmd.zig
index 6fec627..7723e6b 100644
--- a/src/cmd.zig
+++ b/src/cmd.zig
@@ -28,6 +28,7 @@ const Sort = @import("cmd/sort.zig").Sort;
const Move = @import("cmd/move.zig").Move;
const External = @import("cmd/external.zig").External;
const RedirectCommand = @import("cmd/redirect.zig").RedirectCommand;
+const PipeCommand = @import("cmd/pipe.zig").PipeCommand;
pub const BuiltinCommand = union(enum) {
// File-oriented
@@ -149,10 +150,7 @@ pub const BuiltinCommand = union(enum) {
};
pub const Command = union(enum) {
- Pipe: struct {
- left: *Command,
- right: *Command,
- },
+ Pipe: PipeCommand,
Redirect: RedirectCommand,
External: External,
Builtin: BuiltinCommand,
diff --git a/src/cmd/pipe.zig b/src/cmd/pipe.zig
new file mode 100644
index 0000000..4f079cb
--- /dev/null
+++ b/src/cmd/pipe.zig
@@ -0,0 +1,44 @@
+const std = @import("std");
+const Allocator = std.mem.Allocator;
+const print = std.debug.print;
+
+const types = @import("./lib/types.zig");
+const CommandStatus = types.CommandStatus;
+const OutputCapture = types.OutputCapture;
+const InputSource = types.InputSource;
+
+const cmd = @import("../cmd.zig");
+const Command = cmd.Command;
+
+// Function type for executing commands with output capture
+const ExecuteCommandFn = *const fn (Command, Allocator, ?*OutputCapture, ?*InputSource) anyerror!CommandStatus;
+
+pub const PipeCommand = struct {
+ left: *Command,
+ right: *Command,
+
+ pub fn eval(pipe: PipeCommand, allocator: Allocator, output_capture: ?*OutputCapture, input_source: ?*InputSource, executeCommandWithOutput: ExecuteCommandFn) !CommandStatus {
+ _ = input_source; // Pipe handles its own input flow
+
+ // Create output capture for the left command
+ var left_output = OutputCapture.init(allocator);
+ defer left_output.deinit();
+
+ // Execute the left command and capture its output
+ const left_status = try executeCommandWithOutput(pipe.left.*, allocator, &left_output, null);
+
+ // If the left command failed, return its status
+ if (left_status != .Code or left_status.Code != 0) {
+ return left_status;
+ }
+
+ // Create input source from the left command's output
+ const left_output_data = left_output.getContents();
+ var right_input = InputSource.init(left_output_data);
+
+ // Execute the right command with the left command's output as input
+ const right_status = try executeCommandWithOutput(pipe.right.*, allocator, output_capture, &right_input);
+
+ return right_status;
+ }
+};
diff --git a/src/eval.zig b/src/eval.zig
index 9399c75..a689837 100644
--- a/src/eval.zig
+++ b/src/eval.zig
@@ -128,14 +128,8 @@ pub fn executeCommandWithOutput(command: Command, allocator: Allocator, output_c
return redirect.eval(allocator, output_capture, input_source, executeCommandWithOutput);
},
- else => {
- const error_msg = "Command type not implemented\n";
- if (output_capture) |capture| {
- try capture.write(error_msg);
- } else {
- print("{s}", .{error_msg});
- }
- return CommandStatus{ .Code = 1 };
+ .Pipe => |pipe| {
+ return pipe.eval(allocator, output_capture, input_source, executeCommandWithOutput);
},
}
}