#include #include #include #include #include #include #include #include #include #include #include #include #include using os::File; static Result> split_command_into_args(StringView cmd) { return cmd.split(" \n"_sv); } static Result execute_command(StringView command) { auto args = TRY(split_command_into_args(command)); if (args.size() < 1) exit(0); return os::Process::exec(args[0].view(), args.slice()); } Result luna_main(int argc, char** argv) { StringView path; StringView command; bool interactive { false }; SharedPtr input_file; os::ArgumentParser parser; parser.add_description("The Luna system's command shell."_sv); parser.add_positional_argument(path, "path"_sv, "-"_sv); parser.add_value_argument(command, 'c', "command"_sv, true, "execute a single command and then exit"_sv); parser.parse(argc, argv); if (!command.is_empty()) TRY(execute_command(command)); if (path == "-") { input_file = File::standard_input(); interactive = true; } else { input_file = TRY(File::open(path, File::ReadOnly)); input_file->set_close_on_exec(); } while (1) { if (interactive) { auto cwd = TRY(os::FileSystem::working_directory()); printf("sh %s%c ", cwd.chars(), getuid() == 0 ? '#' : '$'); } auto cmd = TRY(input_file->read_line()); if (cmd.is_empty()) break; if (strspn(cmd.chars(), " \n") == cmd.length()) continue; if (!strncmp(cmd.chars(), "cd", 2)) { auto args = TRY(split_command_into_args(cmd.view())); check(args[0].view() == "cd"); if (args.size() == 1) { auto home = TRY(os::FileSystem::home_directory()); TRY(os::FileSystem::change_directory(home.view())); continue; } TRY(os::FileSystem::change_directory(args[1].view())); continue; } pid_t child = TRY(os::Process::fork()); if (child == 0) { TRY(execute_command(cmd.view())); } if (waitpid(child, NULL, 0) < 0) { perror("waitpid"); return 1; } } return 0; }