aboutsummaryrefslogtreecommitdiff
path: root/src/libutil
diff options
context:
space:
mode:
authorJohn Ericson <John.Ericson@Obsidian.Systems>2020-10-15 18:55:03 +0000
committerJohn Ericson <John.Ericson@Obsidian.Systems>2020-10-15 18:55:03 +0000
commitfccef6a7fa713370c0df348f4fe82a2919bf0a33 (patch)
tree1ea93e85d766e980fdf0db333f45e5bbbd95ef14 /src/libutil
parentf6ed1a96b397f0345af029127cfde86bcd0247d2 (diff)
parent11882d7c7ce3b6dc51dd7c0536f9662dc254ac0a (diff)
Merge remote-tracking branch 'upstream/master' into fix-and-ci-static-builds
Diffstat (limited to 'src/libutil')
-rw-r--r--src/libutil/args.cc30
-rw-r--r--src/libutil/args.hh12
-rw-r--r--src/libutil/util.cc29
-rw-r--r--src/libutil/util.hh2
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);