Repositories / jai.git
jai.git
Clone (read-only): git clone http://git.guha-anderson.com/git/jai.git
@@ -286,6 +286,11 @@ opencode`): If the argument contains `=`, then *var* is always treated as a variable, not a pattern, and it is assigned *value* in the jail. + If *value* contains the pattern `${`*envvar*`}`, it will be + replaced by the value of the evironment variable *envvar* at the + time jai was invoked. If value contains `\`, it escapes the next + character. + `--storage` *dir* : Specify an alternate location in which to store private home directories and overlays. The default is `$JAI_CONFIG_DIR` if set, @@ -293,6 +298,9 @@ opencode`): you may wish to use storage on a local file system, as NFS does not support the extended attributes required by overlay file systems. + Like `--setenv`, `--storage` expands `${`*envvar*`}` patterns and +uses `\` to escape the next character. + `--command` *bash-command* : jai launches the jailed program you specify by running "`/bin/bash -c` *bash-command* *cmd* *arg*...". By default, *bash-command* just
@@ -125,7 +125,8 @@ Config::parse_config_file(path file, Options *opts) { bool slash = std::ranges::distance(file.begin(), file.end()) > 1; - if (struct stat sb; !slash && file.extension() != ".conf" && + if (struct stat sb; + !slash && file.extension() != ".conf" && fstatat(home_jai(), file.c_str(), &sb, 0) && errno == ENOENT && ~fstatat(home_jai(), cat(file, ".conf").c_str(), &sb, 0) && S_ISREG(sb.st_mode)) @@ -971,8 +972,11 @@ Config::opt_parser() opts( "--setenv", [this](std::string var) { - if (auto pos = var.find('='); pos != var.npos) - setenv_.insert_or_assign(var.substr(0, pos), var); + if (auto pos = var.find('='); pos != var.npos) { + auto var_eq_val = std::format("{}{}", var.substr(0, pos + 1), + var_expand(var.substr(pos + 1))); + setenv_.insert_or_assign(var.substr(0, pos), var_eq_val); + } else if (auto it = env_filter_.find(var); it != env_filter_.end()) env_filter_.erase(it); else if (var.contains(' ')) @@ -993,10 +997,11 @@ Config::opt_parser() opts( "--storage", [this](std::string_view s) { + auto sd = var_expand(s); if (dir_relative_to_home_) - storagedir_ = homepath_ / s; + storagedir_ = homepath_ / sd; else - storagedir_ = s; + storagedir_ = sd; }, R"(Store overlay and private home directories in DIR (default: $JAI_CONFIG_DIR or $HOME/.jai))",
@@ -10,6 +10,33 @@ #include <sys/syscall.h> #include <unistd.h> +inline const char * +env_or_empty(std::string_view var) +{ + const char *p = getenv(std::string(var).c_str()); + return p ? p : ""; +} + +// Calls exp("VAR"sv) to expand strings like "123${VAR}456". +template<typename Exp = decltype(env_or_empty)> +std::string +var_expand(std::string_view in, Exp &&exp = env_or_empty) + requires requires(std::string r) { r += exp(in); } +{ + std::string ret; + for (std::size_t i = 0, e = in.size(); i < e;) + if (in[i] == '\\') + ret += (++i < e ? in[i++] : '\\'); + else if (size_t j; + in.substr(i, 2) == "${" && (j = in.find('}', i + 2)) != in.npos) { + ret += exp(in.substr(i + 2, j - i - 2)); + i = j + 1; + } + else + ret += in[i++]; + return ret; +} + inline pid_t xfork(std::uint64_t flags = 0) {