script support. scripts run with an independent copy of the environment and aliases. local variables are not imported.

Currently, it for a ".text" extension to check if it's a script; this is a placeholder.
This commit is contained in:
Kelvin Sherlock 2022-11-02 21:22:16 -04:00
parent fd94247aec
commit 6f2b59c4d6
3 changed files with 49 additions and 21 deletions

View File

@ -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;

View File

@ -23,6 +23,10 @@ namespace {
bool tf(long v) { return v; }
bool tf(const EnvironmentEntry &e) {
return tf(static_cast<std::string>(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 "";

View File

@ -56,7 +56,8 @@ public:
typedef std::vector<std::pair<std::string, std::string>> 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<std::string>& argv);
void set_argv(const std::vector<std::string>& 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<class FX>
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