#include #include #include #include #include #include #include #include #include static Result> split_command_into_argv(const char* cmd) { char* str = strdup(cmd); 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; } return result; } [[noreturn]] static void execute_command(const char* command) { Vector argv; bool ok = split_command_into_argv(command).try_move_value_or_error(argv, errno); if (!ok) { perror("failed to parse command"); exit(1); } if (argv[0] == NULL) exit(0); execvp(argv[0], argv.data()); perror(argv[0]); exit(1); } Result luna_main(int argc, char** argv) { StringView file; StringView command; FILE* f; os::ArgumentParser parser; parser.add_positional_argument(file, "file"_sv, "-"_sv); parser.add_value_argument(command, 'c', "command"_sv, true); parser.parse(argc, argv); if (!command.is_empty()) { execute_command(command.chars()); } if (file == "-") f = stdin; else { f = fopen(file.chars(), "r"); if (!f) { perror("fopen"); return 1; } } while (1) { if (file == "-") { char* cwd = getcwd(NULL, 0); if (!cwd) { perror("getcwd"); return 1; } printf("sh %s%c ", cwd, getuid() == 0 ? '#' : '$'); free(cwd); } char cmd[4096]; char* rc = fgets(cmd, sizeof(cmd), f); if (!rc) return 0; if (strspn(cmd, " \n") == strlen(cmd)) continue; pid_t child = fork(); if (child < 0) { perror("fork"); return 1; } if (child == 0) { execute_command(cmd); } if (waitpid(child, NULL, 0) < 0) { perror("waitpid"); return 1; } } }