diff --git a/command.cpp b/command.cpp index 0bea643..a89a120 100644 --- a/command.cpp +++ b/command.cpp @@ -107,6 +107,9 @@ namespace { } + bool is_script(const fs::path &path) { + return path.extension() == ".text"; + } } @@ -359,8 +362,6 @@ int simple_command::execute(Environment &env, const fdmask &fds, bool throwup) { return status; } - if (env.test()) return 0; - if (env.startup()) { fprintf(stderr, "### MPW Shell - startup file may not contain external commands.\n"); return 0; @@ -374,6 +375,23 @@ int simple_command::execute(Environment &env, const fdmask &fds, bool throwup) { //fprintf(stderr, "### MPW Shell - Command \"%s\" was not found.\n", name.c_str()); //return -1; } + + if (is_script(path)) { + // scripts run with an isolated environment. + Environment new_env = env.subshell_environment(); + new_env.set("command", path); + new_env.set_argv(path, p.arguments); + + try { + return read_file(new_env, path, newfds); + } catch (const exit_command_t &ex) { + return ex.value; + } + } + + + if (env.test()) return 0; + env.set("command", path); p.arguments[0] = path; diff --git a/environment.cpp b/environment.cpp index b6e816b..2b602c7 100644 --- a/environment.cpp +++ b/environment.cpp @@ -23,6 +23,10 @@ namespace { bool tf(long v) { return v; } + bool tf(const EnvironmentEntry &e) { + return tf(static_cast(e)); + } + // used for #. base 10 only, extra chars ignored. int to_pound_int(const std::string &s) { if (s.empty()) return 0; @@ -38,6 +42,29 @@ namespace { } + + Environment Environment::subshell_environment() { + /* clone the current environment, do not include local variables */ + Environment env; + env._alias_table = _alias_table; + + auto &table = env._table; + for (const auto &kv : _table) { + const auto &k = kv.first; + const auto &value = kv.second; + if (!value) continue; + + if (k == "echo") env._echo = tf(value); + if (k == "exit") env._exit = tf(value); + if (k == "test") env._test = tf(value); + + table.emplace_hint(table.end(), k, value); + } + + return env; + } + + std::string Environment::get(const std::string & key) const { auto iter = find(key); if (iter == end()) return ""; diff --git a/environment.h b/environment.h index 556de7c..f3cbfe2 100644 --- a/environment.h +++ b/environment.h @@ -56,7 +56,8 @@ public: typedef std::vector> alias_table_type; typedef alias_table_type::const_iterator const_alias_iterator; - //const EnvironmentEntry & lookup(const std::string &s); + + Environment subshell_environment(); void set_argv(const std::string &argv0, const std::vector& argv); void set_argv(const std::vector& argv); @@ -80,10 +81,6 @@ public: bool startup() const noexcept { return _startup; } void startup(bool tf) noexcept { _startup = tf; } - - bool passthrough() const noexcept { return _passthrough; } - void passthrough(bool tf) noexcept { _passthrough = tf; } - template void foreach(FX && fx) { for (const auto &kv : _table) { fx(kv.first, kv.second); }} @@ -133,8 +130,6 @@ public: private: // magic variables. - friend class indent_helper; - int _indent = 0; int _loop = 0; @@ -145,7 +140,6 @@ private: int _status = 0; int _pound = 0; bool _startup = false; - bool _passthrough = false; void set_common(const std::string &, const std::string &, bool); void rebuild_aliases(); @@ -155,16 +149,5 @@ private: alias_table_type _alias_table; }; -/* -class indent_helper { -public: - indent_helper(Environment &e) : env(e) { env._indent++; } - void release() { if (active) { active = false; env._indent--; }} - ~indent_helper() { if (active) env._indent--; } -private: - Environment &env; - bool active = true; -}; -*/ #endif