diff --git a/PiHelper/cli.c b/PiHelper/cli.c index 2651392..f0024ba 100644 --- a/PiHelper/cli.c +++ b/PiHelper/cli.c @@ -78,7 +78,7 @@ int main(int argc, char ** argv) { case 'h': default: print_usage(); - return PIHELPER_HELP; + return PIHELPER_OPERATION_FAILED; } } if (config_path == NULL) { @@ -118,25 +118,35 @@ int main(int argc, char ** argv) { write_log(PIHELPER_LOG_DEBUG, "Reading existing PiHelper config"); config = pihelper_read_config(config_path); } - int retval; + int status; if (config == NULL) { write_log(PIHELPER_LOG_ERROR, "Failed to parse Pi-Helper config at %s", config_path); - retval = 1; + status = PIHELPER_OPERATION_FAILED; } else if (enable && disable != NULL) { print_usage(); - retval = PIHELPER_INVALID_COMMANDS; + status = PIHELPER_OPERATION_FAILED; } else if (enable) { - retval = pihelper_enable_pihole(config); + status = pihelper_enable_pihole(config); } else if (disable != NULL) { - retval = pihelper_disable_pihole(config, disable); + status = pihelper_disable_pihole(config, disable); free(disable); } else { - retval = pihelper_get_status(config); + status = pihelper_get_status(config); } + char * status_message = NULL; + if (status == PIHELPER_ENABLED) { + status_message = "enabled"; + } else if (status == PIHELPER_DISABLED) { + status_message = "disabled"; + } + + if (status_message != NULL) { + write_log(PIHELPER_LOG_INFO, "Pi-hole status: %s", status_message); + } free(config_path); pihelper_free_config(config); - return retval; + return status; } void print_usage() { diff --git a/PiHelper/config.c b/PiHelper/config.c index 5aef902..c87e7e6 100644 --- a/PiHelper/config.c +++ b/PiHelper/config.c @@ -25,8 +25,6 @@ #include #include "config.h" -const int MAX_PIHOLE_API_KEY = 64; - int mkdirs(char * path) { char * curPos = strstr(path, "/") + 1; char parents[strlen(path)]; diff --git a/PiHelper/config.h b/PiHelper/config.h index 15452a7..bde0256 100644 --- a/PiHelper/config.h +++ b/PiHelper/config.h @@ -22,6 +22,8 @@ #include "log.h" #include "pihelper.h" +#define MAX_PIHOLE_API_KEY 64 + int save_config(pihole_config * config, char * config_path); pihole_config * read_config(char * config_path); diff --git a/PiHelper/network.c b/PiHelper/network.c index a417fc6..3713e83 100644 --- a/PiHelper/network.c +++ b/PiHelper/network.c @@ -26,14 +26,6 @@ #include "log.h" #include "network.h" -static char * URL_FORMAT = "http://%s/admin/api.php"; -static int URL_FORMAT_LEN = 22; -static char * AUTH_QUERY = "auth"; -static char * ENABLE_QUERY = "enable"; -static char * DISABLE_QUERY = "disable"; -static char * HTTP_SCHEME = "http://"; -static char * HTTPS_SCHEME = "https://"; - int get_status(pihole_config * config) { write_log(PIHELPER_LOG_DEBUG, "Getting Pi-hole status…"); char * formatted_host = prepend_scheme(config->host); @@ -41,11 +33,11 @@ int get_status(pihole_config * config) { free(formatted_host); if (response == NULL) { write_log(PIHELPER_LOG_ERROR, "Failed to retrieve status for Pi-hole at %s\n", config->host); - return 1; + return PIHELPER_OPERATION_FAILED; } else { - parse_status(response); + int status = parse_status(response); free(response); - return 0; + return status; } } @@ -57,11 +49,11 @@ int enable_pihole(pihole_config * config) { char * response = get(formatted_host); free(formatted_host); if (response == NULL) { - return 1; + return PIHELPER_OPERATION_FAILED; } else { - parse_status(response); + int status = parse_status(response); free(response); - return 0; + return status; } } @@ -77,11 +69,11 @@ int disable_pihole(pihole_config * config, char * duration) { char * response = get(formatted_host); free(formatted_host); if (response == NULL) { - return 1; + return PIHELPER_OPERATION_FAILED; } else { - parse_status(response); + int status = parse_status(response); free(response); - return 0; + return status; } } @@ -145,10 +137,11 @@ static char * prepend_scheme(char * raw_host) { return formatted_host; } -static void parse_status(char * raw_json) { +static int parse_status(char * raw_json) { json_tokener *tok = json_tokener_new(); json_object *jobj = NULL; int stringlen = 0; + int retval = PIHELPER_OPERATION_FAILED; enum json_tokener_error jerr; do { stringlen = strlen(raw_json); @@ -157,19 +150,24 @@ static void parse_status(char * raw_json) { if (jerr != json_tokener_success) { write_log(PIHELPER_LOG_ERROR, "Failed to parse JSON: %s", json_tokener_error_desc(jerr)); json_tokener_free(tok); - return; + return retval; } write_log(PIHELPER_LOG_DEBUG, "%s", json_object_to_json_string_ext(jobj, JSON_C_TO_STRING_PRETTY)); json_object *status; const char * status_string; if (json_pointer_get(jobj, "/status", &status) == 0 && (status_string = json_object_get_string(status)) != NULL) { - printf("Pi-hole status: %s\n", status_string); + if (strstr(status_string, "enabled") == status_string) { + retval = PIHELPER_ENABLED; + } else if (strstr(status_string, "disabled") == status_string) { + retval = PIHELPER_DISABLED; + } } else { write_log(PIHELPER_LOG_DEBUG, "Unable to parse response: %s", raw_json); } json_tokener_free(tok); json_object_put(jobj); + return retval; } static void append_query_parameter(char ** host, char * key, char * value) { diff --git a/PiHelper/network.h b/PiHelper/network.h index cb50276..da64a26 100644 --- a/PiHelper/network.h +++ b/PiHelper/network.h @@ -19,6 +19,14 @@ #ifndef PIHELPER_NETWORK #define PIHELPER_NETWORK +#define URL_FORMAT "http://%s/admin/api.php" +#define URL_FORMAT_LEN 22 +#define AUTH_QUERY "auth" +#define ENABLE_QUERY "enable" +#define DISABLE_QUERY "disable" +#define HTTP_SCHEME "http://" +#define HTTPS_SCHEME "https://" + typedef struct { size_t size; char * body; @@ -51,7 +59,7 @@ int disable_pihole(pihole_config * config, char * duration); static char * get(char endpoint[]); -static void parse_status(char * raw_json); +static int parse_status(char * raw_json); static void append_query_parameter(char ** host, char * key, char * value); diff --git a/PiHelper/pihelper.h b/PiHelper/pihelper.h index 10fb355..c09a067 100644 --- a/PiHelper/pihelper.h +++ b/PiHelper/pihelper.h @@ -18,42 +18,116 @@ */ #ifndef PIHELPER #define PIHELPER -static int PIHELPER_OK = 0; -static int PIHELPER_HELP = 1; -static int PIHELPER_INVALID_COMMANDS = 2; -static int PIHELPER_LOG_DISABLED = -1; -static int PIHELPER_LOG_ERROR = 0; -static int PIHELPER_LOG_WARN = 1; -static int PIHELPER_LOG_INFO = 2; -static int PIHELPER_LOG_DEBUG = 3; +/** + * Use this with pihelper_set_log_level() to disable logging + */ +#define PIHELPER_LOG_DISABLED -1 +/** + * Use this with pihelper_set_log_level() to only log error messages + */ +#define PIHELPER_LOG_ERROR 0 + +/** + * Use this with pihelper_set_log_level() to log error and warning messages + */ +#define PIHELPER_LOG_WARN 1 + +/** + * Use this with pihelper_set_log_level() to log error, warning, and info messages + */ + +#define PIHELPER_LOG_INFO 2 + +/** + * Use this with pihelper_set_log_level() to print all log messages + */ +#define PIHELPER_LOG_DEBUG 3 + +/** + * The return code used when a Pi-hole operation fails + */ +#define PIHELPER_OPERATION_FAILED -1 + +/** + * The return code used to denote that the Pi-hole is enabled + */ +#define PIHELPER_ENABLED 0 + +/** + * The return code used to denote that the Pi-hole is disabled + */ +#define PIHELPER_DISABLED 1 typedef struct { char * host; char * api_key; } pihole_config; +/** + * Call this to change the logging level with one of the PIHELPER_LOG_* constants + */ void pihelper_set_log_level(int level); +/** + * Retrieve the status of the pi-hole. This method does not require an API key to succeed. + * @return PIHELPER_OPERATION_FAILED on failure, or either PIHELPER_ENABLED or PIHELPER_DISABLED + */ int pihelper_get_status(pihole_config * config); +/** + * Enable the pi-hole. This method requires a valid API key to succeed. + * @return PIHELPER_OPERATION_FAILED on failure, or either PIHELPER_ENABLED or PIHELPER_DISABLED + */ int pihelper_enable_pihole(pihole_config * config); +/** + * Disable the pi-hole. This method requires a valid API key to succeed. + * @return PIHELPER_OPERATION_FAILED on failure, or either PIHELPER_ENABLED or PIHELPER_DISABLED + */ int pihelper_disable_pihole(pihole_config * config, char * duration); +/** + * Create a new pihole_config object. The pointer returned here should be passed to pihelper_free_config() + * when it is no longer needed; + * @return A pointer to a pihole_config object or NULL if the system doesn't have enough memory + */ pihole_config * pihelper_new_config(); +/** + * Sets the host for a given config. The memory will be copied, so you can free your copy once it's been + * passed to the config object. + */ void pihelper_config_set_host(pihole_config * config, char * host); +/** + * Sets the password for a given config. The password will be hashed and converted to an API key. Call this + * if you don't already have the API key, otherwise call pihelper_config_set_api_key(). The memory will be + * copied, so you can free your copy once it's been passed to the config object. + */ void pihelper_config_set_password(pihole_config * config, char * password); +/** + * Sets the API key for a given config. The API key is a 64-character double SHA256 hash of the password. If + * you don't have this, call pihelper_config_set_password() instead. The memory will be copied, so you can + * free your copy once it's been passed to the config object. + */ void pihelper_config_set_api_key(pihole_config * config, char * api_key); +/** + * Read the PiHelper config from a file at the given path. + */ pihole_config * pihelper_read_config(char * config_path); +/** + * Save the PiHelper config to a file at the given path. + */ int pihelper_save_config(pihole_config * config, char * config_path); +/** + * Clean up all memory associated with a pihole_config object. + */ void pihelper_free_config(pihole_config * config); #endif