You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

141 lines
3.5 KiB

  1. #ifndef __NGINX_UTIL_H
  2. #define __NGINX_UTIL_H
  3. #include <array>
  4. #include <cerrno>
  5. #include <cstdio>
  6. #include <cstdlib>
  7. #include <cstring>
  8. #include <fstream>
  9. #include <string>
  10. #include <string_view>
  11. #include <thread>
  12. #include <unistd.h>
  13. #include <vector>
  14. #ifndef NO_UBUS
  15. #include "ubus-cxx.hpp"
  16. #endif
  17. static constexpr auto NGINX_UTIL = std::string_view{"/usr/bin/nginx-util"};
  18. static constexpr auto NGINX_CONF = std::string_view{"/etc/nginx/nginx.conf"};
  19. static constexpr auto CONF_DIR = std::string_view{"/etc/nginx/conf.d/"};
  20. static constexpr auto LAN_NAME = std::string_view{"_lan"};
  21. static constexpr auto LAN_LISTEN =std::string_view{"/var/lib/nginx/lan.listen"};
  22. static constexpr auto LAN_LISTEN_DEFAULT =
  23. std::string_view{"/var/lib/nginx/lan.listen.default"};
  24. // mode: optional ios::binary and/or ios::app (default ios::trunc)
  25. void write_file(const std::string_view & name, const std::string & str,
  26. std::ios_base::openmode flag=std::ios::trunc);
  27. // mode: optional ios::binary (internally ios::ate|ios::in)
  28. auto read_file(const std::string_view & name,
  29. std::ios_base::openmode mode=std::ios::in) -> std::string;
  30. // all S must be convertible to const char[]
  31. template<typename ...S>
  32. auto call(const std::string & program, S... args) -> pid_t;
  33. void create_lan_listen();
  34. void init_lan();
  35. void get_env();
  36. // --------------------- partial implementation: ------------------------------
  37. void write_file(const std::string_view & name, const std::string & str,
  38. const std::ios_base::openmode flag)
  39. {
  40. auto tmp = std::string{name};
  41. if ( (flag & std::ios::ate) == 0 && (flag & std::ios::app) == 0 ) {
  42. tmp += ".tmp-XXXXXX";
  43. auto fd = mkstemp(&tmp[0]);
  44. if (fd==-1 || close(fd)!=0)
  45. { throw std::runtime_error("write_file error: cannot access " + tmp); }
  46. }
  47. try {
  48. std::ofstream file(tmp.data(), flag);
  49. if (!file.good()) {
  50. throw std::ofstream::failure
  51. ("write_file error: cannot open " + std::string{tmp});
  52. }
  53. file<<str<<std::flush;
  54. file.close();
  55. } catch(...) {
  56. if (tmp!=name) { remove(tmp.c_str()); } //remove can fail.
  57. throw;
  58. }
  59. if (rename(tmp.c_str(), name.data()) != 0) {
  60. throw std::runtime_error
  61. ("write_file error: cannot move " + tmp + " to " + name.data());
  62. }
  63. }
  64. auto read_file(const std::string_view & name,
  65. const std::ios_base::openmode mode) -> std::string
  66. {
  67. std::ifstream file(name.data(), mode|std::ios::ate);
  68. if (!file.good()) {
  69. throw std::ifstream::failure(
  70. "read_file error: cannot open " + std::string{name});
  71. }
  72. std::string ret{};
  73. const size_t size = file.tellg();
  74. ret.reserve(size);
  75. file.seekg(0);
  76. ret.assign((std::istreambuf_iterator<char>(file)),
  77. std::istreambuf_iterator<char>());
  78. file.close();
  79. return ret;
  80. }
  81. template<typename ...S>
  82. auto call(const char * program, S... args) -> pid_t
  83. {
  84. pid_t pid = fork();
  85. if (pid==0) { //child:
  86. std::array<char *, sizeof...(args)+2> argv =
  87. { strdup(program), strdup(args)..., nullptr };
  88. execv(program, argv.data()); // argv cannot be const char * const[]!
  89. _exit(EXIT_FAILURE); // exec never returns.
  90. } else if (pid>0) { //parent:
  91. return pid;
  92. }
  93. std::string errmsg = "call error: cannot fork (";
  94. errmsg += std::to_string(errno) + "): " + std::strerror(errno);
  95. throw std::runtime_error(errmsg);
  96. }
  97. #endif