diff options
author | John Ericson <John.Ericson@Obsidian.Systems> | 2020-10-15 18:55:03 +0000 |
---|---|---|
committer | John Ericson <John.Ericson@Obsidian.Systems> | 2020-10-15 18:55:03 +0000 |
commit | fccef6a7fa713370c0df348f4fe82a2919bf0a33 (patch) | |
tree | 1ea93e85d766e980fdf0db333f45e5bbbd95ef14 /src/libutil | |
parent | f6ed1a96b397f0345af029127cfde86bcd0247d2 (diff) | |
parent | 11882d7c7ce3b6dc51dd7c0536f9662dc254ac0a (diff) |
Merge remote-tracking branch 'upstream/master' into fix-and-ci-static-builds
Diffstat (limited to 'src/libutil')
-rw-r--r-- | src/libutil/args.cc | 30 | ||||
-rw-r--r-- | src/libutil/args.hh | 12 | ||||
-rw-r--r-- | src/libutil/util.cc | 29 | ||||
-rw-r--r-- | src/libutil/util.hh | 2 |
4 files changed, 63 insertions, 10 deletions
diff --git a/src/libutil/args.cc b/src/libutil/args.cc index 2760b830b..8bd9c8aeb 100644 --- a/src/libutil/args.cc +++ b/src/libutil/args.cc @@ -17,8 +17,20 @@ void Args::addFlag(Flag && flag_) if (flag->shortName) shortFlags[flag->shortName] = flag; } +void Completions::add(std::string completion, std::string description) +{ + assert(description.find('\n') == std::string::npos); + insert(Completion { + .completion = completion, + .description = description + }); +} + +bool Completion::operator<(const Completion & other) const +{ return completion < other.completion || (completion == other.completion && description < other.description); } + bool pathCompletions = false; -std::shared_ptr<std::set<std::string>> completions; +std::shared_ptr<Completions> completions; std::string completionMarker = "___COMPLETE___"; @@ -148,7 +160,7 @@ bool Args::processFlag(Strings::iterator & pos, Strings::iterator end) for (auto & [name, flag] : longFlags) { if (!hiddenCategories.count(flag->category) && hasPrefix(name, std::string(*prefix, 2))) - completions->insert("--" + name); + completions->add("--" + name, flag->description); } } auto i = longFlags.find(string(*pos, 2)); @@ -165,9 +177,9 @@ bool Args::processFlag(Strings::iterator & pos, Strings::iterator end) if (auto prefix = needsCompletion(*pos)) { if (prefix == "-") { - completions->insert("--"); - for (auto & [flag, _] : shortFlags) - completions->insert(std::string("-") + flag); + completions->add("--"); + for (auto & [flagName, flag] : shortFlags) + completions->add(std::string("-") + flagName, flag->description); } } @@ -244,11 +256,11 @@ nlohmann::json Args::toJSON() return res; } -static void hashTypeCompleter(size_t index, std::string_view prefix) +static void hashTypeCompleter(size_t index, std::string_view prefix) { for (auto & type : hashTypes) if (hasPrefix(type, prefix)) - completions->insert(type); + completions->add(type); } Args::Flag Args::Flag::mkHashTypeFlag(std::string && longName, HashType * ht) @@ -292,7 +304,7 @@ static void _completePath(std::string_view prefix, bool onlyDirs) auto st = lstat(globbuf.gl_pathv[i]); if (!S_ISDIR(st.st_mode)) continue; } - completions->insert(globbuf.gl_pathv[i]); + completions->add(globbuf.gl_pathv[i]); } globfree(&globbuf); } @@ -385,7 +397,7 @@ MultiCommand::MultiCommand(const Commands & commands) if (auto prefix = needsCompletion(s)) { for (auto & [name, command] : commands) if (hasPrefix(name, *prefix)) - completions->insert(name); + completions->add(name); } auto i = commands.find(s); if (i == commands.end()) diff --git a/src/libutil/args.hh b/src/libutil/args.hh index f41242e17..26f1bc11b 100644 --- a/src/libutil/args.hh +++ b/src/libutil/args.hh @@ -283,7 +283,17 @@ typedef std::vector<std::pair<std::string, std::string>> Table2; void printTable(std::ostream & out, const Table2 & table); -extern std::shared_ptr<std::set<std::string>> completions; +struct Completion { + std::string completion; + std::string description; + + bool operator<(const Completion & other) const; +}; +class Completions : public std::set<Completion> { +public: + void add(std::string completion, std::string description = ""); +}; +extern std::shared_ptr<Completions> completions; extern bool pathCompletions; std::optional<std::string> needsCompletion(std::string_view s); diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 9804e9a51..53342b5cb 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -1660,4 +1660,33 @@ string showBytes(uint64_t bytes) } +void commonChildInit(Pipe & logPipe) +{ + const static string pathNullDevice = "/dev/null"; + restoreSignals(); + + /* Put the child in a separate session (and thus a separate + process group) so that it has no controlling terminal (meaning + that e.g. ssh cannot open /dev/tty) and it doesn't receive + terminal signals. */ + if (setsid() == -1) + throw SysError("creating a new session"); + + /* Dup the write side of the logger pipe into stderr. */ + if (dup2(logPipe.writeSide.get(), STDERR_FILENO) == -1) + throw SysError("cannot pipe standard error into log file"); + + /* Dup stderr to stdout. */ + if (dup2(STDERR_FILENO, STDOUT_FILENO) == -1) + throw SysError("cannot dup stderr into stdout"); + + /* Reroute stdin to /dev/null. */ + int fdDevNull = open(pathNullDevice.c_str(), O_RDWR); + if (fdDevNull == -1) + throw SysError("cannot open '%1%'", pathNullDevice); + if (dup2(fdDevNull, STDIN_FILENO) == -1) + throw SysError("cannot dup null device into stdin"); + close(fdDevNull); +} + } diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 129d59a97..cafe93702 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -536,6 +536,8 @@ typedef std::function<bool(const Path & path)> PathFilter; extern PathFilter defaultPathFilter; +/* Common initialisation performed in child processes. */ +void commonChildInit(Pipe & logPipe); /* Create a Unix domain socket in listen mode. */ AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode); |