diff options
| author | Lucas Faria Mendes <lucas.oliveira1676@etec.sp.gov.br> | 2025-12-05 05:53:37 +0000 |
|---|---|---|
| committer | Lucas Faria Mendes <lucas.oliveira1676@etec.sp.gov.br> | 2025-12-05 05:53:37 +0000 |
| commit | 2515de92a5ae28edda56deba40c852f36928b294 (patch) | |
| tree | cc048d51ba7dd6fc78376f02e1c12af1161c7d38 /src/main.zig | |
| parent | 695b1fa1dc95d62016978a517b8e8544e486d9b2 (diff) | |
| download | shell-zig-2515de92a5ae28edda56deba40c852f36928b294.tar.gz shell-zig-2515de92a5ae28edda56deba40c852f36928b294.zip | |
codecrafters submit [skip ci]
Diffstat (limited to 'src/main.zig')
| -rw-r--r-- | src/main.zig | 97 |
1 files changed, 5 insertions, 92 deletions
diff --git a/src/main.zig b/src/main.zig index 10c5c1d..a0959ed 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,4 +1,6 @@ const std = @import("std"); +const parser = @import("parser.zig"); +const shell = @import("shell.zig"); var stdin_buffer: [4096]u8 = undefined; var stdin_reader = std.fs.File.stdin().readerStreaming(&stdin_buffer); @@ -7,93 +9,6 @@ const stdin = &stdin_reader.interface; var stdout_writer = std.fs.File.stdout().writerStreaming(&.{}); const stdout = &stdout_writer.interface; -const CommandResult = enum { - continue_loop, - exit_shell, -}; - -fn parseCommand(input: []const u8) struct { name: []const u8, args: ?[]const u8 } { - const space_pos = std.mem.indexOfScalar(u8, input, ' '); - if (space_pos) |pos| { - return .{ - .name = input[0..pos], - .args = input[pos + 1 ..], - }; - } - return .{ - .name = input, - .args = null, - }; -} - -fn isBuiltin(cmd_name: []const u8) bool { - const builtins = [_][]const u8{ "exit", "echo", "type" }; - for (builtins) |builtin| { - if (std.mem.eql(u8, cmd_name, builtin)) { - return true; - } - } - return false; -} - -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; - } - - if (std.mem.eql(u8, cmd_name, "echo")) { - if (args) |a| { - try stdout.print("{s}\n", .{a}); - } else { - try stdout.print("\n", .{}); - } - return .continue_loop; - } - - if (std.mem.eql(u8, cmd_name, "type")) { - 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}); - } - } - return .continue_loop; - } - - 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(); @@ -104,12 +19,10 @@ pub fn main() !void { const command = try stdin.takeDelimiter('\n'); if (command) |cmd| { - const parsed = parseCommand(cmd); - const result = try executeCommand(allocator, parsed.name, parsed.args); + const parsed = parser.parseCommand(cmd); + const result = try shell.executeCommand(allocator, stdout, parsed.name, parsed.args); - if (result == .exit_shell) { - break; - } + if (result == .exit_shell) break; } else { break; } |