diff --git a/CMakeLists.txt b/CMakeLists.txt index 019445a..e68a7c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,9 +14,13 @@ add_subdirectory(mstch) include_directories(${mstch_INCLUDE_DIR}) option(WITH_CMD "Allow running arbitrary commands via templates" ON) +option(WITH_INCLUDE "Allow including arbitrary files via templates" ON) if(WITH_CMD) add_definitions(-DMST_WITH_CMD) endif() +if(WITH_INCLUDE) + add_definitions(-DMST_WITH_INCLUDE) +endif() set(CMAKE_CXX_CLANG_TIDY "clang-tidy;-format-style=file;-checks=*,-llvmlibc-restrict-system-libc-headers,-llvmlibc-implementation-in-namespace,-llvmlibc-callee-namespace,-fuchsia-default-arguments-calls,-modernize-use-trailing-return-type") add_executable(mst mst.cxx) diff --git a/README.rst b/README.rst index 5a76506..245fced 100644 --- a/README.rst +++ b/README.rst @@ -8,8 +8,8 @@ A rather small CLI file templating tool written in C++. Specifically designed to Standing on a shoulders of a wonderful `no1msd/mstch `_ library. **Warning ⚠️**: ``mst`` assumes input is trusted. By design, it **will run arbitrary commands** - specified in templates with ``{{#cmd}}ls -alh *{{/cmd}}`` syntax. This feature can be disabled - by a compile-time flag: ``cmake -DWITH_CMD=OFF ...``. + and **read arbitrary files** as instructed by input file. These features can be disabled + by compile-time flags: ``cmake -DWITH_CMD=OFF -DWITH_INCLUDE=OFF ...``. .. highlight:: bash .. code-block:: console @@ -18,11 +18,11 @@ Standing on a shoulders of a wonderful `no1msd/mstch string { return str; }; ifstream template_file{argv[1]}; string template_content{istreambuf_iterator{template_file}, istreambuf_iterator{}}; - mstch::map ctx{{"include", mstch::lambda{[](const string& filename) -> mstch::node { - ifstream file_fstream{filename}; - if ((file_fstream.rdstate() & ifstream::failbit) != 0) { - throw runtime_error("Can't open file: " + filename); - } - return string{istreambuf_iterator{file_fstream}, istreambuf_iterator{}}; - }}}, + mstch::map ctx{ +#ifdef MST_WITH_INCLUDE + {"include", mstch::lambda{[](const string& filename) -> mstch::node { + ifstream file_fstream{filename}; + if ((file_fstream.rdstate() & ifstream::failbit) != 0) { + throw runtime_error("Can't open file: " + filename); + } + return string{istreambuf_iterator{file_fstream}, istreambuf_iterator{}}; + }}}, +#endif #ifdef MST_WITH_CMD - {"cmd", mstch::lambda{[](const string& cmd) -> mstch::node { - redi::ipstream cmd_stream(cmd); - string stdout{istreambuf_iterator{cmd_stream}, istreambuf_iterator{}}; - cmd_stream.close(); - if (int exitcode = cmd_stream.rdbuf()->status(); cmd_stream.rdbuf()->exited() && exitcode != 0) { - throw runtime_error("Exit status " + to_string(exitcode) + " of command: '" + cmd + "'"); - } - return stdout; - }}}, + {"cmd", mstch::lambda{[](const string& cmd) -> mstch::node { + redi::ipstream cmd_stream(cmd); + string stdout{istreambuf_iterator{cmd_stream}, istreambuf_iterator{}}; + cmd_stream.close(); + if (int exitcode = cmd_stream.rdbuf()->status(); cmd_stream.rdbuf()->exited() && exitcode != 0) { + throw runtime_error("Exit status " + to_string(exitcode) + " of command: '" + cmd + "'"); + } + return stdout; + }}}, #endif - {"env", mstch::lambda{[](const string& env_var_name) -> mstch::node { - if (char* env_var_value = getenv(env_var_name.c_str())) { - return string{env_var_value}; - } - throw runtime_error("Env var doesn't exist: " + env_var_name); - }}}}; + {"env", mstch::lambda{[](const string& env_var_name) -> mstch::node { + if (char* env_var_value = getenv(env_var_name.c_str())) { + return string{env_var_value}; + } + throw runtime_error("Env var doesn't exist: " + env_var_name); + }}}}; for (int i = 2; i + 1 < argc; i += 2) { ctx.emplace(make_pair(string(argv[i]), string(argv[i + 1])));