- #ifndef __NGINX_UTIL_H
- #define __NGINX_UTIL_H
-
- #include <array>
- #include <cerrno>
- #include <cstdio>
- #include <cstdlib>
- #include <cstring>
- #include <fstream>
- #include <string>
- #include <string_view>
- #include <thread>
- #include <unistd.h>
- #include <vector>
-
- #ifndef NO_UBUS
- #include "ubus-cxx.hpp"
- #endif
-
-
- static constexpr auto NGINX_UTIL = std::string_view{"/usr/bin/nginx-util"};
-
- static constexpr auto NGINX_CONF = std::string_view{"/etc/nginx/nginx.conf"};
-
- static constexpr auto CONF_DIR = std::string_view{"/etc/nginx/conf.d/"};
-
- static constexpr auto LAN_NAME = std::string_view{"_lan"};
-
- static constexpr auto LAN_LISTEN =std::string_view{"/var/lib/nginx/lan.listen"};
-
- static constexpr auto LAN_LISTEN_DEFAULT =
- std::string_view{"/var/lib/nginx/lan.listen.default"};
-
-
- // mode: optional ios::binary and/or ios::app (default ios::trunc)
- void write_file(const std::string_view & name, const std::string & str,
- std::ios_base::openmode flag=std::ios::trunc);
-
-
- // mode: optional ios::binary (internally ios::ate|ios::in)
- auto read_file(const std::string_view & name,
- std::ios_base::openmode mode=std::ios::in) -> std::string;
-
-
- // all S must be convertible to const char[]
- template<typename ...S>
- auto call(const std::string & program, S... args) -> pid_t;
-
-
- void create_lan_listen();
-
-
- void init_lan();
-
-
- void get_env();
-
-
-
- // --------------------- partial implementation: ------------------------------
-
-
- void write_file(const std::string_view & name, const std::string & str,
- const std::ios_base::openmode flag)
- {
- auto tmp = std::string{name};
-
- if ( (flag & std::ios::ate) == 0 && (flag & std::ios::app) == 0 ) {
- tmp += ".tmp-XXXXXX";
- auto fd = mkstemp(&tmp[0]);
- if (fd==-1 || close(fd)!=0)
- { throw std::runtime_error("write_file error: cannot access " + tmp); }
- }
-
- try {
- std::ofstream file(tmp.data(), flag);
- if (!file.good()) {
- throw std::ofstream::failure
- ("write_file error: cannot open " + std::string{tmp});
- }
-
- file<<str<<std::flush;
-
- file.close();
- } catch(...) {
- if (tmp!=name) { remove(tmp.c_str()); } //remove can fail.
- throw;
- }
-
- if (rename(tmp.c_str(), name.data()) != 0) {
- throw std::runtime_error
- ("write_file error: cannot move " + tmp + " to " + name.data());
- }
- }
-
-
- auto read_file(const std::string_view & name,
- const std::ios_base::openmode mode) -> std::string
- {
- std::ifstream file(name.data(), mode|std::ios::ate);
- if (!file.good()) {
- throw std::ifstream::failure(
- "read_file error: cannot open " + std::string{name});
- }
-
- std::string ret{};
- const size_t size = file.tellg();
- ret.reserve(size);
-
- file.seekg(0);
- ret.assign((std::istreambuf_iterator<char>(file)),
- std::istreambuf_iterator<char>());
-
- file.close();
- return ret;
- }
-
-
- template<typename ...S>
- auto call(const char * program, S... args) -> pid_t
- {
- pid_t pid = fork();
-
- if (pid==0) { //child:
- std::array<char *, sizeof...(args)+2> argv =
- { strdup(program), strdup(args)..., nullptr };
-
- execv(program, argv.data()); // argv cannot be const char * const[]!
-
- _exit(EXIT_FAILURE); // exec never returns.
- } else if (pid>0) { //parent:
- return pid;
- }
-
- std::string errmsg = "call error: cannot fork (";
- errmsg += std::to_string(errno) + "): " + std::strerror(errno);
- throw std::runtime_error(errmsg);
- }
-
-
- #endif
|