| 99 | } // namespace FEXServerLogging |
| 100 | |
| 101 | bool InterpreterHandler(fextl::string* Filename, const fextl::string& RootFS, fextl::vector<fextl::string>* args) { |
| 102 | int FD {-1}; |
| 103 | |
| 104 | // Attempt to open the filename from the rootfs first. |
| 105 | FD = open(fextl::fmt::format("{}{}", RootFS, *Filename).c_str(), O_RDONLY | O_CLOEXEC); |
| 106 | if (FD == -1) { |
| 107 | // Failing that, attempt to open the filename directly. |
| 108 | FD = open(Filename->c_str(), O_RDONLY | O_CLOEXEC); |
| 109 | if (FD == -1) { |
| 110 | return false; |
| 111 | } |
| 112 | } |
| 113 | |
| 114 | std::array<char, 257> Header; |
| 115 | const auto ChunkSize = 257l; |
| 116 | const auto ReadSize = pread(FD, Header.data(), ChunkSize, 0); |
| 117 | close(FD); |
| 118 | |
| 119 | const auto Data = std::span<char>(Header.data(), ReadSize); |
| 120 | |
| 121 | // Is the file large enough for shebang |
| 122 | if (ReadSize <= 2) { |
| 123 | return false; |
| 124 | } |
| 125 | |
| 126 | // Handle shebang files |
| 127 | if (Data[0] == '#' && Data[1] == '!') { |
| 128 | std::string_view InterpreterLine {Data.begin() + 2, // strip off "#!" prefix |
| 129 | std::find(Data.begin(), Data.end(), '\n')}; |
| 130 | const auto ShebangArguments = FHU::ParseArgumentsFromString(InterpreterLine); |
| 131 | |
| 132 | // Executable argument |
| 133 | *Filename = ShebangArguments.at(0); |
| 134 | |
| 135 | // Insert all the arguments at the start |
| 136 | args->insert(args->begin(), ShebangArguments.begin(), ShebangArguments.end()); |
| 137 | } |
| 138 | return true; |
| 139 | } |
| 140 | |
| 141 | bool RanAsInterpreter(bool ExecutedWithFD) { |
| 142 | return ExecutedWithFD || FEXLOADER_AS_INTERPRETER; |