diff options
author | Peter Elliott <pelliott@ualberta.ca> | 2021-04-03 13:57:31 -0600 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-04-12 14:06:24 +0200 |
commit | eca20e92daf402cbcc3f57c240da8eec5050e0fc (patch) | |
tree | 8794f1c7e7aba9488bf9c6cead9840bf5ce981ab | |
parent | 938924f36de1f335903608c28c4ba5284d5dd883 (diff) | |
download | serenity-eca20e92daf402cbcc3f57c240da8eec5050e0fc.zip |
Userland: Add support for -S to env command
- Refactor env to use Core::ArgsParser
- create symlink from /bin/env to /usr/bin/env for compatiability
l--------- | Base/usr/bin/env | 1 | ||||
-rw-r--r-- | Userland/Utilities/env.cpp | 60 |
2 files changed, 40 insertions, 21 deletions
diff --git a/Base/usr/bin/env b/Base/usr/bin/env new file mode 120000 index 0000000000..24234ae18e --- /dev/null +++ b/Base/usr/bin/env @@ -0,0 +1 @@ +/bin/env
\ No newline at end of file diff --git a/Userland/Utilities/env.cpp b/Userland/Utilities/env.cpp index 630ff81749..8f9332bd91 100644 --- a/Userland/Utilities/env.cpp +++ b/Userland/Utilities/env.cpp @@ -24,6 +24,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <LibCore/ArgsParser.h> #include <LibCore/DirIterator.h> #include <stdio.h> #include <stdlib.h> @@ -36,40 +37,57 @@ int main(int argc, char** argv) return 1; } - const char* filename = nullptr; + bool ignore_env = false; + const char* split_string = nullptr; + Vector<const char*> values; - for (int idx = 1; idx < argc; ++idx) { - if (idx == 1) { - if (StringView { argv[idx] } == "-i" || StringView { argv[idx] } == "--ignore-environment") { - clearenv(); - continue; - } - } - if (StringView { argv[idx] }.contains('=')) { - putenv(argv[idx]); + Core::ArgsParser args_parser; + args_parser.add_option(ignore_env, "Start with an empty environment", "ignore-environment", 'i'); + args_parser.add_option(split_string, "Process and split S into separate arguments; used to pass multiple arguments on shebang lines", "split-string", 'S', "S"); + + args_parser.add_positional_argument(values, "Environment and commands", "env/command", Core::ArgsParser::Required::No); + args_parser.parse(argc, argv); + + if (ignore_env) + clearenv(); + + size_t argv_start; + for (argv_start = 0; argv_start < values.size(); ++argv_start) { + if (StringView { values[argv_start] }.contains('=')) { + putenv(const_cast<char*>(values[argv_start])); } else { - filename = argv[idx]; - argv += idx; break; } } - if (filename == nullptr) { + Vector<String> split_string_storage; + Vector<const char*> new_argv; + if (split_string) { + for (auto view : StringView(split_string).split_view(' ')) { + split_string_storage.append(view); + } + for (auto& str : split_string_storage) { + new_argv.append(str.characters()); + } + } + + for (size_t i = argv_start; i < values.size(); ++i) { + new_argv.append(values[i]); + } + + if (new_argv.size() == 0) { for (auto entry = environ; *entry != nullptr; ++entry) printf("%s\n", *entry); return 0; } - String filepath = Core::find_executable_in_path(filename); - - if (filepath.is_null()) { - warnln("no {} in path", filename); - return 1; - } + new_argv.append(nullptr); - execv(filepath.characters(), argv); + const char* executable = new_argv[0]; + char* const* new_argv_ptr = const_cast<char* const*>(&new_argv[0]); - perror("execv"); + execvp(executable, new_argv_ptr); + perror("execvp"); return 1; } |