diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/executor.zig | 116 | ||||
| -rw-r--r-- | src/shell.zig | 37 |
2 files changed, 109 insertions, 44 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]); diff --git a/src/shell.zig b/src/shell.zig index 53aaf3f..15046d5 100644 --- a/src/shell.zig +++ b/src/shell.zig @@ -153,26 +153,41 @@ pub fn executePipeline( return .continue_loop; } - const left_path = try path.findInPath(allocator, left_parsed.name); + const left_is_builtin = builtins.isBuiltin(left_parsed.name); + const right_is_builtin = builtins.isBuiltin(right_parsed.name); + + const left_path = if (left_is_builtin) null else try path.findInPath(allocator, left_parsed.name); defer if (left_path) |p| allocator.free(p); - if (left_path == null) { + if (!left_is_builtin and left_path == null) { try stdout.print("{s}: command not found\n", .{left_parsed.name}); return .continue_loop; } - const right_path = try path.findInPath(allocator, right_parsed.name); + const right_path = if (right_is_builtin) null else try path.findInPath(allocator, right_parsed.name); defer if (right_path) |p| allocator.free(p); - if (right_path == null) { + if (!right_is_builtin and right_path == null) { try stdout.print("{s}: command not found\n", .{right_parsed.name}); return .continue_loop; } - const left_argv = try parser.parseArgs(allocator, left_parsed.name, left_parsed.args); - defer allocator.free(left_argv); - - const right_argv = try parser.parseArgs(allocator, right_parsed.name, right_parsed.args); - defer allocator.free(right_argv); - - try executor.runExternalPipeline(allocator, left_path.?, left_argv, right_path.?, right_argv); + const left_argv = if (left_is_builtin) null else try parser.parseArgs(allocator, left_parsed.name, left_parsed.args); + defer if (left_argv) |argv| allocator.free(argv); + + const right_argv = if (right_is_builtin) null else try parser.parseArgs(allocator, right_parsed.name, right_parsed.args); + defer if (right_argv) |argv| allocator.free(argv); + + try executor.runPipeline( + allocator, + left_path, + left_is_builtin, + left_parsed.name, + left_parsed.args, + left_argv, + right_path, + right_is_builtin, + right_parsed.name, + right_parsed.args, + right_argv, + ); return .continue_loop; } |