|
3 | 3 | #include <iostream> |
4 | 4 | #include <future> |
5 | 5 | #include <simdjson.h> |
| 6 | +#include <yaml-cpp/yaml.h> |
6 | 7 |
|
7 | 8 | /* |
8 | 9 | * Two handles for two theads. |
9 | 10 | * One for cdn-cgi/trace and one for DNS IP |
10 | 11 | */ |
11 | 12 |
|
12 | | -std::size_t writeData(char* incomingBuffer, std::size_t size, std::size_t count, std::string* data) { |
| 13 | +static constexpr const char* configPath {[]() { |
| 14 | + #if (defined(__linux__) || defined(__unix__) || defined(__unix)) && !defined(__FreeBSD__) |
| 15 | + return "/etc/cloudflare-ddns/config.yaml"; |
| 16 | + #elif defined(__FreeBSD__) |
| 17 | + return "/usr/local/etc/cloudflare-ddns/config.yaml"; |
| 18 | + #elif defined(_WIN32) |
| 19 | + return "Where should I store the config file?"; |
| 20 | + #else |
| 21 | + return "Unknown"; |
| 22 | + #endif |
| 23 | +}()}; |
| 24 | + |
| 25 | +std::size_t writeData(char* incomingBuffer, const std::size_t size, const std::size_t count, std::string* data) { |
13 | 26 | data->append(incomingBuffer, size * count); |
14 | 27 | return size * count; |
15 | 28 | } |
@@ -46,20 +59,61 @@ std::string getLocalIp() { |
46 | 59 | } |
47 | 60 |
|
48 | 61 | // NOT thread-safe, writes into a buffer and uses an handle both owned elsewhere |
49 | | -void getDnsRecordResponse(CURL** curlHandle, std::string_view requestUri) { |
| 62 | +void getDnsRecordResponse(CURL** curlHandle, const std::string_view requestUri) { |
50 | 63 | curl_easy_setopt(*curlHandle, CURLOPT_HTTPGET, 1L); |
51 | 64 | curl_easy_setopt(*curlHandle, CURLOPT_URL, requestUri.data()); |
52 | 65 | curl_easy_perform(*curlHandle); |
53 | 66 | } |
54 | 67 |
|
55 | 68 | int main(int argc, char* argv[]) { |
56 | | - if (argc != 4) { |
57 | | - std::cerr << "Usage: cloudflare-ddns <API token> <Zone ID> <DNS record name>\n"; |
| 69 | + std::string apiToken; |
| 70 | + std::string zoneId; |
| 71 | + std::string recordName; |
| 72 | + |
| 73 | + if (argc == 1) { |
| 74 | + try { |
| 75 | + const YAML::Node config {YAML::LoadFile(configPath)}; |
| 76 | + apiToken = config["api-token"].as<std::string>(); |
| 77 | + zoneId = config["zone-id"].as<std::string>(); |
| 78 | + recordName = config["record-name"].as<std::string>(); |
| 79 | + } |
| 80 | + catch (const YAML::BadFile&) { |
| 81 | + std::cerr << "No config file found in " << configPath << '\n'; |
| 82 | + return EXIT_FAILURE; |
| 83 | + } |
| 84 | + catch (const YAML::Exception&) { |
| 85 | + std::cerr << "Bad config file\n"; |
| 86 | + return EXIT_FAILURE; |
| 87 | + } |
| 88 | + } |
| 89 | + else if (argc == 3) { |
| 90 | + const std::string_view configPath {argv[2]}; |
| 91 | + try { |
| 92 | + const YAML::Node config {YAML::LoadFile(configPath.data())}; |
| 93 | + apiToken = config["api-token"].as<std::string>(); |
| 94 | + zoneId = config["zone-id"].as<std::string>(); |
| 95 | + recordName = config["record-name"].as<std::string>(); |
| 96 | + } |
| 97 | + catch (const YAML::BadFile&) { |
| 98 | + std::cerr << "No config file found in " << configPath << '\n'; |
| 99 | + return EXIT_FAILURE; |
| 100 | + } |
| 101 | + catch (const YAML::Exception&) { |
| 102 | + std::cerr << "Bad config file\n"; |
| 103 | + return EXIT_FAILURE; |
| 104 | + } |
| 105 | + } |
| 106 | + else if (argc == 4) { |
| 107 | + apiToken = argv[1]; |
| 108 | + zoneId = argv[2]; |
| 109 | + recordName = argv[3]; |
| 110 | + } |
| 111 | + else { |
| 112 | + std::cerr |
| 113 | + << "Bad usage! You can run the program without arguments and load the config in" << configPath |
| 114 | + << " or pass the API token, the Zone ID and the DNS record name as arguments\n"; |
58 | 115 | return EXIT_FAILURE; |
59 | 116 | } |
60 | | - const std::string_view apiToken {argv[1]}; |
61 | | - const std::string zoneId {argv[2]}; |
62 | | - const std::string recordName {argv[3]}; |
63 | 117 |
|
64 | 118 | curl_global_init(CURL_GLOBAL_SSL); |
65 | 119 |
|
|
0 commit comments