summaryrefslogtreecommitdiff
path: root/src/main.zig
diff options
context:
space:
mode:
authorLucas Faria Mendes <lucas.oliveira1676@etec.sp.gov.br>2025-12-05 05:53:37 +0000
committerLucas Faria Mendes <lucas.oliveira1676@etec.sp.gov.br>2025-12-05 05:53:37 +0000
commit2515de92a5ae28edda56deba40c852f36928b294 (patch)
treecc048d51ba7dd6fc78376f02e1c12af1161c7d38 /src/main.zig
parent695b1fa1dc95d62016978a517b8e8544e486d9b2 (diff)
downloadshell-zig-2515de92a5ae28edda56deba40c852f36928b294.tar.gz
shell-zig-2515de92a5ae28edda56deba40c852f36928b294.zip
codecrafters submit [skip ci]
Diffstat (limited to 'src/main.zig')
-rw-r--r--src/main.zig97
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;
}