diff options
| author | Lucas Faria Mendes <lucas.oliveira1676@etec.sp.gov.br> | 2025-12-05 08:04:01 +0000 |
|---|---|---|
| committer | Lucas Faria Mendes <lucas.oliveira1676@etec.sp.gov.br> | 2025-12-05 08:04:01 +0000 |
| commit | 6430308cdfd85ebad6819e5c87fe3036b8f21435 (patch) | |
| tree | 478ddfe9e27d52ff89ceb5f058ec2f7638efb452 /src/executor.zig | |
| parent | 16c43f33f8f7302a07778153aff59f565592bad8 (diff) | |
| download | shell-zig-6430308cdfd85ebad6819e5c87fe3036b8f21435.tar.gz shell-zig-6430308cdfd85ebad6819e5c87fe3036b8f21435.zip | |
codecrafters submit [skip ci]
Diffstat (limited to 'src/executor.zig')
| -rw-r--r-- | src/executor.zig | 116 |
1 files changed, 83 insertions, 33 deletions
diff --git a/src/executor.zig b/src/executor.zig index 02ec159..354e724 100644 --- a/src/executor.zig +++ b/src/executor.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const builtins = @import("builtins.zig"); pub fn runExternalProgram(allocator: std.mem.Allocator, program_path: []const u8, argv: []const []const u8) !void { const argv_z = try allocator.allocSentinel(?[*:0]const u8, argv.len, null); @@ -104,34 +105,49 @@ pub fn runExternalProgramWithRedirect(allocator: std.mem.Allocator, program_path } } -pub fn runExternalPipeline(allocator: std.mem.Allocator, program1_path: []const u8, argv1: []const []const u8, program2_path: []const u8, argv2: []const []const u8) !void { - const argv1_z = try allocator.allocSentinel(?[*:0]const u8, argv1.len, null); - defer allocator.free(argv1_z); - for (argv1, 0..) |arg, i| { - argv1_z[i] = (try allocator.dupeZ(u8, arg)).ptr; - } - defer { - for (argv1_z[0..argv1.len]) |arg_ptr| { - if (arg_ptr) |ptr| allocator.free(std.mem.span(ptr)); - } - } - - const argv2_z = try allocator.allocSentinel(?[*:0]const u8, argv2.len, null); - defer allocator.free(argv2_z); - for (argv2, 0..) |arg, i| { - argv2_z[i] = (try allocator.dupeZ(u8, arg)).ptr; - } - defer { - for (argv2_z[0..argv2.len]) |arg_ptr| { - if (arg_ptr) |ptr| allocator.free(std.mem.span(ptr)); - } +fn runBuiltinInChild( + allocator: std.mem.Allocator, + cmd_name: []const u8, + args: ?[]const u8, + stdin_fd: std.posix.fd_t, + stdout_fd: std.posix.fd_t, +) noreturn { + // Redirect stdin/stdout to provided fds (already valid) + if (stdin_fd != 0) std.posix.dup2(stdin_fd, 0) catch {}; + if (stdout_fd != 1) std.posix.dup2(stdout_fd, 1) catch {}; + + var out_file = std.fs.File{ .handle = 1 }; + var out_writer = out_file.writerStreaming(&.{}); + const w = &out_writer.interface; + + if (std.mem.eql(u8, cmd_name, "echo")) { + builtins.executeEcho(w, args) catch {}; + } else if (std.mem.eql(u8, cmd_name, "type")) { + builtins.executeType(allocator, w, args) catch {}; + } else if (std.mem.eql(u8, cmd_name, "pwd")) { + builtins.executePwd(allocator, w) catch {}; + } else if (std.mem.eql(u8, cmd_name, "cd")) { + builtins.executeCd(allocator, w, args) catch {}; + } else if (std.mem.eql(u8, cmd_name, "exit")) { + // exit inside pipeline child just exits child } - const program1_path_z = try allocator.dupeZ(u8, program1_path); - defer allocator.free(program1_path_z); - const program2_path_z = try allocator.dupeZ(u8, program2_path); - defer allocator.free(program2_path_z); + std.posix.exit(0); +} +pub fn runPipeline( + allocator: std.mem.Allocator, + left_path: ?[]const u8, + left_builtin: bool, + left_name: []const u8, + left_args: ?[]const u8, + left_argv: ?[]const []const u8, + right_path: ?[]const u8, + right_builtin: bool, + right_name: []const u8, + right_args: ?[]const u8, + right_argv: ?[]const []const u8, +) !void { const fds = try std.posix.pipe(); const pid1 = try std.posix.fork(); @@ -139,10 +155,27 @@ pub fn runExternalPipeline(allocator: std.mem.Allocator, program1_path: []const std.posix.close(fds[0]); try std.posix.dup2(fds[1], 1); std.posix.close(fds[1]); - _ = std.posix.execveZ(program1_path_z, argv1_z, std.c.environ) catch { - std.posix.exit(1); - }; - unreachable; + + if (left_builtin) { + runBuiltinInChild(allocator, left_name, left_args, 0, 1); + } else { + const argv1_z = try allocator.allocSentinel(?[*:0]const u8, left_argv.?.len, @as(?[*:0]const u8, null)); + defer allocator.free(argv1_z); + for (left_argv.?, 0..) |arg, i| { + argv1_z[i] = (try allocator.dupeZ(u8, arg)).ptr; + } + defer { + for (argv1_z[0..left_argv.?.len]) |arg_ptr| { + if (arg_ptr) |ptr| allocator.free(std.mem.span(ptr)); + } + } + const program1_path_z = try allocator.dupeZ(u8, left_path.?); + defer allocator.free(program1_path_z); + _ = std.posix.execveZ(program1_path_z, argv1_z, std.c.environ) catch { + std.posix.exit(1); + }; + unreachable; + } } const pid2 = try std.posix.fork(); @@ -150,10 +183,27 @@ pub fn runExternalPipeline(allocator: std.mem.Allocator, program1_path: []const std.posix.close(fds[1]); try std.posix.dup2(fds[0], 0); std.posix.close(fds[0]); - _ = std.posix.execveZ(program2_path_z, argv2_z, std.c.environ) catch { - std.posix.exit(1); - }; - unreachable; + + if (right_builtin) { + runBuiltinInChild(allocator, right_name, right_args, 0, 1); + } else { + const argv2_z = try allocator.allocSentinel(?[*:0]const u8, right_argv.?.len, @as(?[*:0]const u8, null)); + defer allocator.free(argv2_z); + for (right_argv.?, 0..) |arg, i| { + argv2_z[i] = (try allocator.dupeZ(u8, arg)).ptr; + } + defer { + for (argv2_z[0..right_argv.?.len]) |arg_ptr| { + if (arg_ptr) |ptr| allocator.free(std.mem.span(ptr)); + } + } + const program2_path_z = try allocator.dupeZ(u8, right_path.?); + defer allocator.free(program2_path_z); + _ = std.posix.execveZ(program2_path_z, argv2_z, std.c.environ) catch { + std.posix.exit(1); + }; + unreachable; + } } std.posix.close(fds[0]); |