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 &params)
@@ -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 &params)
 {
 	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};