diff options
Diffstat (limited to 'src/main.zig')
| -rw-r--r-- | src/main.zig | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/src/main.zig b/src/main.zig index 92067a4..10c5c1d 100644 --- a/src/main.zig +++ b/src/main.zig @@ -36,7 +36,33 @@ fn isBuiltin(cmd_name: []const u8) bool { return false; } -fn executeCommand(cmd_name: []const u8, args: ?[]const u8) !CommandResult { +fn findInPath(allocator: std.mem.Allocator, cmd_name: []const u8) !?[]const u8 { + const path_env = std.process.getEnvVarOwned(allocator, "PATH") catch return null; + defer allocator.free(path_env); + + var it = std.mem.splitScalar(u8, path_env, ':'); + while (it.next()) |dir| { + const full_path = std.fs.path.join(allocator, &[_][]const u8{ dir, cmd_name }) catch continue; + defer allocator.free(full_path); + + const file = std.fs.openFileAbsolute(full_path, .{}) catch continue; + const stat = file.stat() catch { + file.close(); + continue; + }; + file.close(); + + const mode = stat.mode; + const has_exec = (mode & 0o111) != 0; + if (!has_exec) continue; + + return try allocator.dupe(u8, full_path); + } + + return null; +} + +fn executeCommand(allocator: std.mem.Allocator, cmd_name: []const u8, args: ?[]const u8) !CommandResult { if (std.mem.eql(u8, cmd_name, "exit")) { return .exit_shell; } @@ -54,6 +80,9 @@ fn executeCommand(cmd_name: []const u8, args: ?[]const u8) !CommandResult { if (args) |a| { if (isBuiltin(a)) { try stdout.print("{s} is a shell builtin\n", .{a}); + } else if (try findInPath(allocator, a)) |path| { + defer allocator.free(path); + try stdout.print("{s} is {s}\n", .{ a, path }); } else { try stdout.print("{s}: not found\n", .{a}); } @@ -61,19 +90,22 @@ fn executeCommand(cmd_name: []const u8, args: ?[]const u8) !CommandResult { return .continue_loop; } - // Command not found try stdout.print("{s}: command not found\n", .{cmd_name}); return .continue_loop; } pub fn main() !void { + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + defer _ = gpa.deinit(); + const allocator = gpa.allocator(); + while (true) { try stdout.print("$ ", .{}); const command = try stdin.takeDelimiter('\n'); if (command) |cmd| { const parsed = parseCommand(cmd); - const result = try executeCommand(parsed.name, parsed.args); + const result = try executeCommand(allocator, parsed.name, parsed.args); if (result == .exit_shell) { break; |