Mercurial > irccd
changeset 178:084081b24024
Irccd: support shell templates, #407
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 26 May 2016 21:20:46 +0200 |
parents | 254bbc0f13b5 |
children | ef527409e638 |
files | lib/irccd/util.cpp lib/irccd/util.hpp |
diffstat | 2 files changed, 46 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/lib/irccd/util.cpp Thu May 26 18:52:09 2016 +0200 +++ b/lib/irccd/util.cpp Thu May 26 21:20:46 2016 +0200 @@ -16,6 +16,8 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "sysconfig.hpp" + #include <algorithm> #include <cassert> #include <cctype> @@ -25,7 +27,14 @@ #include <sstream> #include <stdexcept> -#include "sysconfig.hpp" +#if defined(HAVE_POPEN) +#include <array> +#include <cerrno> +#include <cstring> +#include <functional> +#include <memory> +#endif + #include "util.hpp" #include "unicode.hpp" @@ -68,7 +77,7 @@ inline bool isReserved(char token) noexcept { - return token == '#' || token == '@' || token == '$'; + return token == '#' || token == '@' || token == '$' || token == '!'; } std::string substituteDate(const std::string &text, const Substitution ¶ms) @@ -154,6 +163,34 @@ return oss.str(); } +std::string substituteShell(const std::string &command) +{ +#if defined(HAVE_POPEN) + std::unique_ptr<std::FILE, std::function<void (std::FILE *)>> fp(popen(command.c_str(), "r"), pclose); + + if (fp == nullptr) + throw std::runtime_error(std::strerror(errno)); + + std::string result; + std::array<char, 128> buffer; + std::size_t n; + + while ((n = std::fread(buffer.data(), 1, 128, fp.get())) > 0) + result.append(buffer.data(), n); + if (std::ferror(fp.get())) + throw std::runtime_error(std::strerror(errno)); + + // Erase final '\n'. + auto it = result.find('\n'); + if (it != std::string::npos) + result.erase(it); + + return result; +#else + throw std::runtime_error("shell template not available"); +#endif +} + std::string substitute(std::string::const_iterator &it, std::string::const_iterator &end, char token, const Substitution ¶ms) { assert(isReserved(token)); @@ -185,7 +222,11 @@ break; case '@': if (params.flags & Substitution::IrcAttrs) - substituteAttributes(content); + value = substituteAttributes(content); + break; + case '!': + if (params.flags & Substitution::Shell) + value = substituteShell(content); break; default: break;
--- a/lib/irccd/util.hpp Thu May 26 18:52:09 2016 +0200 +++ b/lib/irccd/util.hpp Thu May 26 21:20:46 2016 +0200 @@ -73,7 +73,8 @@ Date = (1 << 0), //!< date templates Keywords = (1 << 1), //!< keywords Env = (1 << 2), //!< environment variables - IrcAttrs = (1 << 3), //!< IRC escape codes + Shell = (1 << 3), //!< command line command + IrcAttrs = (1 << 4) //!< IRC escape codes }; std::uint8_t flags{Date | Keywords | Env | IrcAttrs};