diff --git a/apps/sh.cpp b/apps/sh.cpp index c929d2f5..009b21b4 100644 --- a/apps/sh.cpp +++ b/apps/sh.cpp @@ -15,44 +15,17 @@ using os::File; -static Result> split_command_into_argv(StringView cmd, char** out) +static Result> split_command_into_args(StringView cmd) { - char* str = strdup(cmd.chars()); - - Vector result; - - char* segment = strtok(str, " \n"); - TRY(result.try_append(segment)); - - if (segment == NULL) return result; - - for (;;) - { - segment = strtok(NULL, " \n"); - TRY(result.try_append(segment)); - - if (segment == NULL) return result; - } - - if (out) *out = str; - - return result; + return cmd.split(" \n"_sv); } -[[noreturn]] static void execute_command(StringView command) +static Result execute_command(StringView command) { - Vector argv; - bool ok = split_command_into_argv(command, nullptr).try_move_value_or_error(argv, errno); - if (!ok) - { - perror("failed to parse command"); - exit(1); - } + auto args = TRY(split_command_into_args(command)); + if (args.size() < 1) exit(0); - if (argv[0] == NULL) exit(0); - execvp(argv[0], argv.data()); - perror(argv[0]); - exit(1); + return os::Process::exec(args[0].view(), args.slice()); } Result luna_main(int argc, char** argv) @@ -68,7 +41,7 @@ Result luna_main(int argc, char** argv) parser.add_value_argument(command, 'c', "command"_sv, true); parser.parse(argc, argv); - if (!command.is_empty()) execute_command(command); + if (!command.is_empty()) TRY(execute_command(command)); if (path == "-") { @@ -98,10 +71,10 @@ Result luna_main(int argc, char** argv) { char* copy = nullptr; - auto args = TRY(split_command_into_argv(cmd.view(), ©)); - check("cd"_sv == args[0]); + auto args = TRY(split_command_into_args(cmd.view())); + check(args[0].view() == "cd"); - if (args.size() == 2) + if (args.size() == 1) { auto home = TRY(os::FileSystem::home_directory()); if (chdir(home.chars()) < 0) perror("cd"); @@ -109,14 +82,14 @@ Result luna_main(int argc, char** argv) continue; } - if (chdir(args[1]) < 0) perror("cd"); + if (chdir(args[1].chars()) < 0) perror("cd"); free(copy); continue; } pid_t child = TRY(os::Process::fork()); - if (child == 0) { execute_command(cmd.view()); } + if (child == 0) { TRY(execute_command(cmd.view())); } if (waitpid(child, NULL, 0) < 0) { diff --git a/libluna/include/luna/Slice.h b/libluna/include/luna/Slice.h new file mode 100644 index 00000000..66448f97 --- /dev/null +++ b/libluna/include/luna/Slice.h @@ -0,0 +1,52 @@ +#pragma once +#include + +template class Slice +{ + typedef T* Iterator; + typedef const T* ConstIterator; + + public: + Slice(T* data, usize size) : m_data(data), m_size(size) + { + } + + const T* data() const + { + return m_data; + } + + T* data() + { + return m_data; + } + + usize size() const + { + return m_size; + } + + Iterator begin() + { + return m_data; + } + + ConstIterator begin() const + { + return m_data; + } + + Iterator end() + { + return m_data + m_size; + } + + ConstIterator end() const + { + return m_data + m_size; + } + + private: + T* const m_data; + const usize m_size; +}; diff --git a/libluna/include/luna/Vector.h b/libluna/include/luna/Vector.h index 76175703..9678a2d4 100644 --- a/libluna/include/luna/Vector.h +++ b/libluna/include/luna/Vector.h @@ -2,6 +2,7 @@ #include #include #include +#include #include template class Vector @@ -156,6 +157,18 @@ template class Vector return m_data; } + Slice slice() + { + return { m_data, m_size }; + } + + Slice slice(usize index) + { + check(index < m_size); + + return { m_data + index, m_size - index }; + } + usize capacity() const { return m_capacity; diff --git a/libos/include/os/Process.h b/libos/include/os/Process.h index c80c3465..507e783a 100644 --- a/libos/include/os/Process.h +++ b/libos/include/os/Process.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include namespace os @@ -8,5 +9,7 @@ namespace os { public: static Result fork(); + + static Result exec(StringView path, Slice args, bool search_in_path = true); }; } diff --git a/libos/src/Process.cpp b/libos/src/Process.cpp index c8024cdc..19a569c9 100644 --- a/libos/src/Process.cpp +++ b/libos/src/Process.cpp @@ -1,4 +1,6 @@ #include + +#include #include #include @@ -9,4 +11,17 @@ namespace os long rc = syscall(SYS_fork); return Result::from_syscall(rc); } + + Result Process::exec(StringView path, Slice args, bool search_in_path) + { + Vector argv; + for (const auto& arg : args) { TRY(argv.try_append(arg.chars())); } + TRY(argv.try_append(nullptr)); + + if (search_in_path) execvp(path.chars(), const_cast(argv.data())); + else + execv(path.chars(), const_cast(argv.data())); + + return err(errno); + } }