Repositories / jai.git
jai.git
Clone (read-only): git clone http://git.guha-anderson.com/git/jai.git
@@ -688,7 +688,7 @@ do_main(int argc, char **argv) opts("-u", [&] { opt_u = true; }, "Unmount sandboxed file systems"); opts( "-n", "--name", - [&] (std::string optarg) { + [&](std::string optarg) { conf.sandbox_name_ = optarg; if (conf.sandbox_name_.is_absolute() || std::ranges::distance(conf.sandbox_name_.begin(), @@ -724,12 +724,6 @@ version 3 or later; see the file named COPYING for details.)", }); option_help = opts.help(); - restore.reset(); - - if (!set_mode) - conf.mode_ = - conf.sandbox_name_ == "default" ? Config::kCasual : Config::kStrict; - std::vector<char *> cmd; try { cmd.append_range(opts.parse_argv(argc, argv)); @@ -737,6 +731,30 @@ version 3 or later; see the file named COPYING for details.)", std::println("{}", e.what()); usage(2); } + if (!cmd.empty() && *cmd[0] != '.' && !strchr(cmd[0], '/')) { + path cfpath = std::format("{}.conf", cmd[0]); + Fd cf = openat(conf.home_jai(), cfpath.c_str(), O_RDONLY); + if (!cf) { + if (errno != ENOENT) + syserr("{}", fdpath(conf.home_jai(), cfpath)); + cfpath = "default.conf"; + Fd cf = openat(conf.home_jai(), cfpath.c_str(), O_RDONLY); + if (errno != ENOENT) + syserr("{}", fdpath(conf.home_jai(), cfpath)); + } + if (cf) + try { + opts.parse_file(read_file(*cf)); + } catch (Options::Error &e) { + err<Options::Error>("{}:{}", fdpath(*cf), e.what()); + } + } + + restore.reset(); + + if (!set_mode) + conf.mode_ = + conf.sandbox_name_ == "default" ? Config::kCasual : Config::kStrict; if (opt_u) { if (opt_D || !opt_d.empty() || !cmd.empty())
@@ -261,13 +261,13 @@ public: auto ha = act.has_arg(); if (!arg.empty()) { if (ha == kNoArg) - err<OptionError>("option {} takes no argument", opt); + err<Error>("option {} takes no argument", opt); act(arg.substr(1)); } else if (ha != kArg) act(); else if (i + 1 == args.size()) - err<OptionError>("option {} requires an argument", opt); + err<Error>("option {} requires an argument", opt); else act(args[++i]); } @@ -284,7 +284,7 @@ public: else if (ha == kOptArg) act(); else if (i + 1 == args.size()) - err<OptionError>("option -{} requires an argument", optarg[j]); + err<Error>("option -{} requires an argument", optarg[j]); else act(args[++i]); break; @@ -302,61 +302,68 @@ public: { static constexpr std::string_view ws = " \t\r"; static constexpr std::string_view wsnl = " \t\r\n"; + static constexpr std::string_view wsnleq = " \t\r\n="; const size_t sz = text.size(); auto clamp = [sz](size_t n) { return std::min(n, sz); }; for (size_t pos = 0; pos < sz;) { - if ((pos = text.find_first_not_of(wsnl, pos)) >= sz) - break; - if (text[pos] == '#') { - pos = text.find('\n', pos); - continue; - } - auto optend = clamp(text.find_first_of(wsnl, pos)); - std::string optarg = "--"; - optarg += text.substr(pos, optend - pos); - if ((pos = text.find_first_not_of(ws, optend)) >= sz || - text[pos] == '\n') { - parse_argspan(std::span{&optarg, 1}); - continue; - } - optarg += '='; - - bool escape = false, last_escaped = false; - for (; pos < sz && (escape || text[pos] != '\n'); ++pos) { - if (text[pos] == '\r') + try { + if ((pos = text.find_first_not_of(wsnl, pos)) >= sz) + break; + if (text[pos] == '#') { + pos = text.find('\n', pos); continue; - if (!escape) { - last_escaped = false; - if (text[pos] == '\\') - escape = true; - else - optarg += text[pos]; + } + auto optend = clamp(text.find_first_of(wsnleq, pos)); + std::string optarg = "--"; + optarg += text.substr(pos, optend - pos); + if ((pos = text.find_first_not_of(ws, optend)) >= sz || + text[pos] == '\n') { + parse_argspan(std::span{&optarg, 1}); continue; } - escape = false; - last_escaped = true; - switch (text[pos]) { - case 't': - optarg += '\t'; - break; - case 'r': - optarg += '\r'; - break; - case 'n': - optarg += '\n'; - break; - case '\n': - pos = clamp(text.find_first_not_of(ws, pos + 1) - 1); - break; - default: - optarg += text[pos]; - break; + if (text[pos] != '=') + optarg += '='; + + bool escape = false, last_escaped = false; + for (; pos < sz && (escape || text[pos] != '\n'); ++pos) { + if (text[pos] == '\r') + continue; + if (!escape) { + last_escaped = false; + if (text[pos] == '\\') + escape = true; + else + optarg += text[pos]; + continue; + } + escape = false; + last_escaped = true; + switch (text[pos]) { + case 't': + optarg += '\t'; + break; + case 'r': + optarg += '\r'; + break; + case 'n': + optarg += '\n'; + break; + case '\n': + pos = clamp(text.find_first_not_of(ws, pos + 1) - 1); + break; + default: + optarg += text[pos]; + break; + } } + if (!last_escaped) + while (wsnl.contains(optarg.back())) + optarg.resize(optarg.size() - 1); + parse_argspan(std::span{&optarg, 1}); + } catch (const Error &e) { + auto lineno = std::count(text.begin(), text.begin() + clamp(pos), '\n'); + err<Error>("{}:{}", lineno, e.what()); } - if (!last_escaped) - while (wsnl.contains(optarg.back())) - optarg.resize(optarg.size() - 1); - parse_argspan(std::span{&optarg, 1}); } }