Introduce ot::shell_escape

This commit is contained in:
Frédéric Mangano 2020-11-01 10:41:24 +01:00
parent d54bada7e6
commit 639d46ed0f
3 changed files with 34 additions and 1 deletions

View File

@ -34,6 +34,7 @@
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
namespace ot {
@ -165,6 +166,9 @@ private:
iconv_t cd; /**< conversion descriptor */
};
/** Escape a string so that a POSIX shell interprets it as a single argument. */
std::string shell_escape(std::string_view word);
/**
* Execute the editor process specified in editor using execlp. Wait for the process to exit and
* return st::ok on success, or st::child_process_failed if it did not exit with 0.

View File

@ -137,6 +137,26 @@ ot::status ot::encoding_converter::operator()(const char* in, size_t n, std::str
return ot::st::ok;
}
std::string ot::shell_escape(std::string_view word)
{
std::string escaped_word;
// Pre-allocate the result, assuming most of the time enclosing it in single quotes is enough.
escaped_word.reserve(2 + word.size());
escaped_word += '\'';
for (char c : word) {
if (c == '\'')
escaped_word += "'\\''";
else if (c == '!')
escaped_word += "'\\!'";
else
escaped_word += c;
}
escaped_word += '\'';
return escaped_word;
}
ot::status ot::run_editor(const char* editor, const char* path)
{
pid_t pid = fork();

View File

@ -49,10 +49,19 @@ void check_converter()
is(rc, ot::st::badly_encoded, "conversion from bad UTF-8 fails");
}
void check_shell_esape()
{
is(ot::shell_escape("foo"), "'foo'", "simple string");
is(ot::shell_escape("a'b"), "'a'\\''b'", "string with a simple quote");
is(ot::shell_escape("a!b"), "'a'\\!'b'", "string with a bang");
is(ot::shell_escape("a!b'c!d'e"), "'a'\\!'b'\\''c'\\!'d'\\''e'", "string with a bang");
}
int main(int argc, char **argv)
{
plan(2);
plan(3);
run(check_partial_files, "test partial files");
run(check_converter, "test encoding converter");
run(check_shell_esape, "test shell escaping");
return 0;
}