summaryrefslogtreecommitdiff
path: root/src/main.zig
diff options
context:
space:
mode:
authorLucas Faria Mendes <lucas.oliveira1676@etec.sp.gov.br>2025-12-05 05:10:11 +0000
committerLucas Faria Mendes <lucas.oliveira1676@etec.sp.gov.br>2025-12-05 05:10:11 +0000
commit695b1fa1dc95d62016978a517b8e8544e486d9b2 (patch)
treec41667e76816e81cef5d7574afbfe075176174a3 /src/main.zig
parent69df1ebb0f34499afa36c0c9d76700442c8355a8 (diff)
downloadshell-zig-695b1fa1dc95d62016978a517b8e8544e486d9b2.tar.gz
shell-zig-695b1fa1dc95d62016978a517b8e8544e486d9b2.zip
codecrafters submit [skip ci]
Diffstat (limited to 'src/main.zig')
-rw-r--r--src/main.zig38
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;