diff options
author | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2025-08-13 21:10:47 +0200 |
---|---|---|
committer | Matthias Andreas Benkard <code@mail.matthias.benkard.de> | 2025-08-13 21:10:47 +0200 |
commit | c623a9171b711f1a0cbd761e4fc8ae5f64a52c95 (patch) | |
tree | 33108d4eb4c9c58713400adc0cdcc931b518ab4b /src | |
parent | 4a5f0120b68e752a0c61597eec6daf55f01c2582 (diff) |
Support COPY CON.
Diffstat (limited to 'src')
-rw-r--r-- | src/eval.zig | 87 |
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"; |