summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMatthias Andreas Benkard <code@mail.matthias.benkard.de>2025-08-13 21:10:47 +0200
committerMatthias Andreas Benkard <code@mail.matthias.benkard.de>2025-08-13 21:10:47 +0200
commitc623a9171b711f1a0cbd761e4fc8ae5f64a52c95 (patch)
tree33108d4eb4c9c58713400adc0cdcc931b518ab4b /src
parent4a5f0120b68e752a0c61597eec6daf55f01c2582 (diff)
Support COPY CON.
Diffstat (limited to 'src')
-rw-r--r--src/eval.zig87
1 files changed, 83 insertions, 4 deletions
diff --git a/src/eval.zig b/src/eval.zig
index e320713..2b55c21 100644
--- a/src/eval.zig
+++ b/src/eval.zig
@@ -554,13 +554,92 @@ fn executeCommandWithOutput(command: Command, allocator: Allocator, output_captu
// Handle source file
const source_path = switch (copy.from) {
.Con => {
- const error_msg = "Cannot copy from CON\n";
+ // COPY CON <file> - copy from console to file
+ const dest_path = switch (copy.to) {
+ .Con => {
+ const error_msg = "Cannot copy from CON to CON\n";
+ if (output_capture) |capture| {
+ try capture.write(error_msg);
+ } else {
+ print("{s}", .{error_msg});
+ }
+ return CommandStatus{ .Code = 1 };
+ },
+ .Lpt1, .Lpt2, .Lpt3, .Prn => {
+ const error_msg = "Cannot copy to device\n";
+ if (output_capture) |capture| {
+ try capture.write(error_msg);
+ } else {
+ print("{s}", .{error_msg});
+ }
+ return CommandStatus{ .Code = 1 };
+ },
+ .Path => |path| path,
+ };
+
+ // Create the destination file
+ const dest_file = std.fs.cwd().createFile(dest_path, .{}) catch |err| {
+ const error_msg = switch (err) {
+ error.AccessDenied => "Access denied\n",
+ error.PathAlreadyExists => "File already exists - use different name\n",
+ else => "Cannot create file\n",
+ };
+ if (output_capture) |capture| {
+ try capture.write(error_msg);
+ } else {
+ print("{s}", .{error_msg});
+ }
+ return CommandStatus{ .Code = 1 };
+ };
+ defer dest_file.close();
+
+ // Read from stdin and write to file until EOF (Ctrl+Z on DOS)
+ const stdin = std.io.getStdIn().reader();
+ var line_count: u32 = 0;
+
+ // Skip output redirection since we're doing interactive input
+ if (output_capture == null) {
+ // In interactive mode, show no prompt (DOS behavior)
+ }
+
+ while (true) {
+ if (stdin.readUntilDelimiterOrEofAlloc(allocator, '\n', 4096)) |maybe_line| {
+ if (maybe_line) |line| {
+ defer allocator.free(line);
+
+ // Check for Ctrl+Z (EOF marker)
+ if (line.len == 1 and line[0] == 26) { // ASCII 26 = Ctrl+Z
+ break;
+ }
+
+ // Remove trailing \r if present (Windows line endings)
+ const clean_line = if (line.len > 0 and line[line.len - 1] == '\r')
+ line[0 .. line.len - 1]
+ else
+ line;
+
+ // Write line to file with DOS line ending
+ try dest_file.writeAll(clean_line);
+ try dest_file.writeAll("\r\n");
+ line_count += 1;
+ } else {
+ // EOF reached
+ break;
+ }
+ } else |_| {
+ // Error reading input
+ break;
+ }
+ }
+
+ const msg = try std.fmt.allocPrint(allocator, " 1 File(s) copied\n", .{});
+ defer allocator.free(msg);
if (output_capture) |capture| {
- try capture.write(error_msg);
+ try capture.write(msg);
} else {
- print("{s}", .{error_msg});
+ print("{s}", .{msg});
}
- return CommandStatus{ .Code = 1 };
+ return CommandStatus{ .Code = 0 };
},
.Lpt1, .Lpt2, .Lpt3, .Prn => {
const error_msg = "Cannot copy from device\n";